scs 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +8 -8
- data/lib/scs/ffi.rb +1 -7
- data/lib/scs/version.rb +1 -1
- data/vendor/scs/CITATION.cff +1 -1
- data/vendor/scs/CMakeLists.txt +55 -7
- data/vendor/scs/Makefile +9 -9
- data/vendor/scs/README.md +2 -1
- data/vendor/scs/include/aa.h +1 -1
- data/vendor/scs/include/cones.h +14 -11
- data/vendor/scs/include/glbopts.h +26 -64
- data/vendor/scs/include/linalg.h +2 -1
- data/vendor/scs/include/linsys.h +13 -13
- data/vendor/scs/include/normalize.h +6 -5
- data/vendor/scs/include/scs.h +43 -87
- data/vendor/scs/include/scs_types.h +34 -0
- data/vendor/scs/include/scs_work.h +83 -0
- data/vendor/scs/linsys/cpu/direct/private.c +86 -73
- data/vendor/scs/linsys/cpu/direct/private.h +2 -2
- data/vendor/scs/linsys/cpu/indirect/private.c +42 -33
- data/vendor/scs/linsys/cpu/indirect/private.h +1 -2
- data/vendor/scs/linsys/csparse.c +3 -3
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +6 -6
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +6 -1
- data/vendor/scs/linsys/external/amd/amd_order.c +5 -5
- data/vendor/scs/linsys/gpu/gpu.h +8 -11
- data/vendor/scs/linsys/gpu/indirect/private.c +72 -49
- data/vendor/scs/linsys/gpu/indirect/private.h +14 -13
- data/vendor/scs/linsys/scs_matrix.c +26 -46
- data/vendor/scs/linsys/scs_matrix.h +4 -4
- data/vendor/scs/scs.mk +1 -1
- data/vendor/scs/src/aa.c +13 -4
- data/vendor/scs/src/cones.c +143 -92
- data/vendor/scs/src/linalg.c +25 -0
- data/vendor/scs/src/normalize.c +26 -26
- data/vendor/scs/src/rw.c +48 -12
- data/vendor/scs/src/scs.c +104 -110
- data/vendor/scs/src/scs_version.c +8 -6
- data/vendor/scs/src/util.c +1 -1
- data/vendor/scs/test/minunit.h +6 -1
- data/vendor/scs/test/problem_utils.h +28 -35
- data/vendor/scs/test/problems/degenerate.h +1 -1
- data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -1
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +1 -1
- data/vendor/scs/test/problems/infeasible_tiny_qp.h +1 -1
- data/vendor/scs/test/problems/qafiro_tiny_qp.h +3 -3
- data/vendor/scs/test/problems/random_prob.h +1 -1
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +1 -1
- data/vendor/scs/test/problems/small_lp.h +3 -1
- data/vendor/scs/test/problems/small_qp.h +352 -0
- data/vendor/scs/test/problems/{test_fails.h → test_validation.h} +3 -3
- data/vendor/scs/test/problems/unbounded_tiny_qp.h +1 -1
- data/vendor/scs/test/random_socp_prob.c +1 -1
- data/vendor/scs/test/run_from_file.c +1 -1
- data/vendor/scs/test/run_tests.c +23 -14
- metadata +8 -5
data/vendor/scs/include/scs.h
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
/* This file contains the outward facing SCS API. */
|
2
|
+
/* It includes all the input/output data structs and the API functions. */
|
3
|
+
|
1
4
|
#ifndef SCS_H_GUARD
|
2
5
|
#define SCS_H_GUARD
|
3
6
|
|
@@ -5,20 +8,34 @@
|
|
5
8
|
extern "C" {
|
6
9
|
#endif
|
7
10
|
|
8
|
-
|
11
|
+
/* Contains definitions of primitive types `scs_int` and `scs_float`. */
|
12
|
+
#include "scs_types.h"
|
9
13
|
|
10
|
-
|
11
|
-
#include "glbopts.h"
|
14
|
+
/* The following abstract structs are implemented later. */
|
12
15
|
|
13
16
|
/** Struct containing acceleration workspace. Implemented by acceleration. */
|
14
|
-
typedef struct
|
17
|
+
typedef struct ACCEL_WORK AaWork;
|
15
18
|
/** Struct containing cone projection workspace. Implemented by cones. */
|
16
19
|
typedef struct SCS_CONE_WORK ScsConeWork;
|
17
20
|
/** Struct containing linear system workspace. Implemented by linear solver. */
|
18
21
|
typedef struct SCS_LIN_SYS_WORK ScsLinSysWork;
|
22
|
+
/** Struct containing SCS workspace. Implemented in `scs_work.h`. */
|
23
|
+
typedef struct SCS_WORK ScsWork;
|
24
|
+
|
25
|
+
/* SCS returns one of the following integer exit flags: */
|
26
|
+
#define SCS_INFEASIBLE_INACCURATE (-7)
|
27
|
+
#define SCS_UNBOUNDED_INACCURATE (-6)
|
28
|
+
#define SCS_SIGINT (-5)
|
29
|
+
#define SCS_FAILED (-4)
|
30
|
+
#define SCS_INDETERMINATE (-3)
|
31
|
+
#define SCS_INFEASIBLE (-2) /* primal infeasible, dual unbounded */
|
32
|
+
#define SCS_UNBOUNDED (-1) /* primal unbounded, dual infeasible */
|
33
|
+
#define SCS_UNFINISHED (0) /* never returned, used as placeholder */
|
34
|
+
#define SCS_SOLVED (1)
|
35
|
+
#define SCS_SOLVED_INACCURATE (2)
|
19
36
|
|
20
|
-
/** This defines the data matrices which should be supplied in
|
21
|
-
* format with zero based indexing.
|
37
|
+
/** This defines the data matrices which should be supplied in compressed
|
38
|
+
* sparse column format with zero based indexing.
|
22
39
|
*/
|
23
40
|
typedef struct {
|
24
41
|
/** Matrix values, size: number of non-zeros. */
|
@@ -120,7 +137,10 @@ typedef struct {
|
|
120
137
|
|
121
138
|
/** Contains primal-dual solution arrays or a certificate of infeasibility.
|
122
139
|
* Check the exit flag to determine whether this contains a solution or a
|
123
|
-
* certificate.
|
140
|
+
* certificate. If when passed into SCS the members `x`, `y`, `s` are
|
141
|
+
* NULL then SCS will allocate memory for them which should be managed
|
142
|
+
* by the user to prevent memory leaks.
|
143
|
+
*/
|
124
144
|
typedef struct {
|
125
145
|
/** Primal variable. */
|
126
146
|
scs_float *x;
|
@@ -136,6 +156,8 @@ typedef struct {
|
|
136
156
|
scs_int iter;
|
137
157
|
/** Status string, e.g. 'solved'. */
|
138
158
|
char status[128];
|
159
|
+
/** Linear system solver used. */
|
160
|
+
char lin_sys_solver[128];
|
139
161
|
/** Status as scs_int, defined in glbopts.h. */
|
140
162
|
scs_int status_val;
|
141
163
|
/** Number of updates to scale. */
|
@@ -176,78 +198,8 @@ typedef struct {
|
|
176
198
|
scs_float accel_time;
|
177
199
|
} ScsInfo;
|
178
200
|
|
179
|
-
/* the following structs are not exposed to user */
|
180
|
-
|
181
|
-
/** Contains normalization variables. */
|
182
|
-
typedef struct {
|
183
|
-
scs_float *D, *E; /* for normalization */
|
184
|
-
scs_float primal_scale, dual_scale;
|
185
|
-
} ScsScaling;
|
186
|
-
|
187
|
-
/** Holds residual information. */
|
188
|
-
typedef struct {
|
189
|
-
scs_int last_iter;
|
190
|
-
scs_float xt_p_x; /* x' P x */
|
191
|
-
scs_float xt_p_x_tau; /* x'Px * tau^2 *not* divided out */
|
192
|
-
scs_float ctx;
|
193
|
-
scs_float ctx_tau; /* tau *not* divided out */
|
194
|
-
scs_float bty;
|
195
|
-
scs_float bty_tau; /* tau *not* divided out */
|
196
|
-
scs_float pobj; /* primal objective */
|
197
|
-
scs_float dobj; /* dual objective */
|
198
|
-
scs_float gap; /* pobj - dobj */
|
199
|
-
scs_float tau;
|
200
|
-
scs_float kap;
|
201
|
-
scs_float res_pri;
|
202
|
-
scs_float res_dual;
|
203
|
-
scs_float res_infeas;
|
204
|
-
scs_float res_unbdd_p;
|
205
|
-
scs_float res_unbdd_a;
|
206
|
-
/* tau NOT divided out */
|
207
|
-
scs_float *ax, *ax_s, *px, *aty, *ax_s_btau, *px_aty_ctau;
|
208
|
-
} ScsResiduals;
|
209
|
-
|
210
|
-
/** Workspace for SCS */
|
211
|
-
typedef struct {
|
212
|
-
/* x_prev = x from previous iteration */
|
213
|
-
scs_int time_limit_reached; /* set if the time-limit is reached */
|
214
|
-
scs_float *u, *u_t;
|
215
|
-
scs_float *v, *v_prev;
|
216
|
-
scs_float *rsk; /* rsk [ r; s; kappa ] */
|
217
|
-
scs_float *h; /* h = [c; b] */
|
218
|
-
scs_float *g; /* g = (I + M)^{-1} h */
|
219
|
-
scs_float *lin_sys_warm_start; /* linear system warm-start (indirect only) */
|
220
|
-
scs_float *rho_y_vec; /* vector of rho y parameters (affects cone project) */
|
221
|
-
AaWork *accel; /* struct for acceleration workspace */
|
222
|
-
scs_float *b_orig, *c_orig; /* original b and c vectors */
|
223
|
-
scs_float *b_normalized, *c_normalized; /* normalized b and c vectors */
|
224
|
-
scs_int m, n; /* A has m rows, n cols */
|
225
|
-
ScsMatrix *A; /* (possibly normalized) A matrix */
|
226
|
-
ScsMatrix *P; /* (possibly normalized) P matrix */
|
227
|
-
ScsLinSysWork *p; /* struct populated by linear system solver */
|
228
|
-
ScsScaling *scal; /* contains the re-scaling data */
|
229
|
-
ScsConeWork *cone_work; /* workspace for the cone projection step */
|
230
|
-
scs_int *cone_boundaries; /* array with boundaries of cones */
|
231
|
-
scs_int cone_boundaries_len; /* total length of cones */
|
232
|
-
/* normalized and unnormalized residuals */
|
233
|
-
ScsResiduals *r_orig, *r_normalized;
|
234
|
-
/* track x,y,s as alg progresses, tau *not* divided out */
|
235
|
-
ScsSolution *xys_orig, *xys_normalized;
|
236
|
-
/* updating scale params workspace */
|
237
|
-
scs_float sum_log_scale_factor;
|
238
|
-
scs_int last_scale_update_iter, n_log_scale_factor, scale_updates;
|
239
|
-
/* aa norm stat */
|
240
|
-
scs_float aa_norm;
|
241
|
-
scs_int rejected_accel_steps, accepted_accel_steps;
|
242
|
-
scs_float setup_time; /* time taken for setup phase (milliseconds) */
|
243
|
-
scs_float scale; /* current scale parameter */
|
244
|
-
const ScsData *d;
|
245
|
-
const ScsCone *k;
|
246
|
-
const ScsSettings *stgs; /* contains solver settings specified by user */
|
247
|
-
} ScsWork;
|
248
|
-
|
249
201
|
/*
|
250
|
-
*
|
202
|
+
* Main library API.
|
251
203
|
*/
|
252
204
|
|
253
205
|
/**
|
@@ -270,24 +222,24 @@ typedef struct {
|
|
270
222
|
* @param stgs SCS solver settings.
|
271
223
|
* @return Solver work struct.
|
272
224
|
*/
|
273
|
-
ScsWork *
|
225
|
+
ScsWork *scs_init(const ScsData *d, const ScsCone *k, const ScsSettings *stgs);
|
274
226
|
|
275
227
|
/**
|
276
|
-
* Solve quadratic cone program initialized by
|
228
|
+
* Solve quadratic cone program initialized by scs_init.
|
277
229
|
*
|
278
230
|
* @param w Workspace allocated by init.
|
279
231
|
* @param sol Solver solution struct, will contain solution at termination.
|
280
232
|
* @param info Solver info reporting.
|
281
233
|
* @return Flag containing problem status (see \a glbopts.h).
|
282
234
|
*/
|
283
|
-
scs_int
|
235
|
+
scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info);
|
284
236
|
|
285
237
|
/**
|
286
238
|
* Clean up allocated SCS workspace.
|
287
239
|
*
|
288
240
|
* @param w Workspace allocated by init, will be deallocated.
|
289
241
|
*/
|
290
|
-
void
|
242
|
+
void scs_finish(ScsWork *w);
|
291
243
|
|
292
244
|
/**
|
293
245
|
* Solve quadratic cone program defined by data in d and cone k.
|
@@ -297,7 +249,8 @@ void SCS(finish)(ScsWork *w);
|
|
297
249
|
* @param d Problem data.
|
298
250
|
* @param k Cone data.
|
299
251
|
* @param stgs SCS solver settings.
|
300
|
-
* @param sol Solution will be stored here.
|
252
|
+
* @param sol Solution will be stored here. If members `x`, `y`, `s` are
|
253
|
+
* NULL then SCS will allocate memory for them.
|
301
254
|
* @param info Information about the solve will be stored here.
|
302
255
|
* @return Flag that determines solve type (see \a glbopts.h).
|
303
256
|
*/
|
@@ -309,11 +262,14 @@ scs_int scs(const ScsData *d, const ScsCone *k, const ScsSettings *stgs,
|
|
309
262
|
*
|
310
263
|
* @param stgs Settings struct that will be populated.
|
311
264
|
*/
|
312
|
-
void
|
265
|
+
void scs_set_default_settings(ScsSettings *stgs);
|
313
266
|
|
314
|
-
|
315
|
-
|
316
|
-
|
267
|
+
/**
|
268
|
+
* Helper function simply returns the current version of SCS as a string.
|
269
|
+
*
|
270
|
+
* @return SCS version as a string.
|
271
|
+
*/
|
272
|
+
const char *scs_version(void);
|
317
273
|
|
318
274
|
#ifdef __cplusplus
|
319
275
|
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
/*
|
2
|
+
* Definitions of primitive types used in SCS.
|
3
|
+
*/
|
4
|
+
|
5
|
+
#ifndef SCS_TYPES_H_GUARD
|
6
|
+
#define SCS_TYPES_H_GUARD
|
7
|
+
|
8
|
+
#ifdef __cplusplus
|
9
|
+
extern "C" {
|
10
|
+
#endif
|
11
|
+
|
12
|
+
#ifdef DLONG
|
13
|
+
/*#ifdef _WIN64
|
14
|
+
#include <stdint.h>
|
15
|
+
typedef int64_t scs_int;
|
16
|
+
#else
|
17
|
+
typedef long scs_int;
|
18
|
+
#endif
|
19
|
+
*/
|
20
|
+
typedef long long scs_int;
|
21
|
+
#else
|
22
|
+
typedef int scs_int;
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#ifndef SFLOAT
|
26
|
+
typedef double scs_float;
|
27
|
+
#else
|
28
|
+
typedef float scs_float;
|
29
|
+
#endif
|
30
|
+
|
31
|
+
#ifdef __cplusplus
|
32
|
+
}
|
33
|
+
#endif
|
34
|
+
#endif
|
@@ -0,0 +1,83 @@
|
|
1
|
+
/*
|
2
|
+
* Define ScsWork and related internal-only structs (not part of external API).
|
3
|
+
*/
|
4
|
+
|
5
|
+
#ifndef SCS_WORK_H_GUARD
|
6
|
+
#define SCS_WORK_H_GUARD
|
7
|
+
|
8
|
+
#ifdef __cplusplus
|
9
|
+
extern "C" {
|
10
|
+
#endif
|
11
|
+
|
12
|
+
/** Contains normalization variables. */
|
13
|
+
typedef struct {
|
14
|
+
scs_float *D, *E; /* for normalization */
|
15
|
+
scs_int m; /* Length of D */
|
16
|
+
scs_int n; /* Length of E */
|
17
|
+
scs_float primal_scale, dual_scale;
|
18
|
+
} ScsScaling;
|
19
|
+
|
20
|
+
/** Holds residual information. */
|
21
|
+
typedef struct {
|
22
|
+
scs_int last_iter;
|
23
|
+
scs_float xt_p_x; /* x' P x */
|
24
|
+
scs_float xt_p_x_tau; /* x'Px * tau^2 *not* divided out */
|
25
|
+
scs_float ctx;
|
26
|
+
scs_float ctx_tau; /* tau *not* divided out */
|
27
|
+
scs_float bty;
|
28
|
+
scs_float bty_tau; /* tau *not* divided out */
|
29
|
+
scs_float pobj; /* primal objective */
|
30
|
+
scs_float dobj; /* dual objective */
|
31
|
+
scs_float gap; /* pobj - dobj */
|
32
|
+
scs_float tau;
|
33
|
+
scs_float kap;
|
34
|
+
scs_float res_pri;
|
35
|
+
scs_float res_dual;
|
36
|
+
scs_float res_infeas;
|
37
|
+
scs_float res_unbdd_p;
|
38
|
+
scs_float res_unbdd_a;
|
39
|
+
/* tau NOT divided out */
|
40
|
+
scs_float *ax, *ax_s, *px, *aty, *ax_s_btau, *px_aty_ctau;
|
41
|
+
} ScsResiduals;
|
42
|
+
|
43
|
+
/** Workspace for SCS */
|
44
|
+
struct SCS_WORK {
|
45
|
+
/* x_prev = x from previous iteration */
|
46
|
+
scs_int time_limit_reached; /* set if the time-limit is reached */
|
47
|
+
scs_float *u, *u_t;
|
48
|
+
scs_float *v, *v_prev;
|
49
|
+
scs_float *rsk; /* rsk [ r; s; kappa ] */
|
50
|
+
scs_float *h; /* h = [c; b] */
|
51
|
+
scs_float *g; /* g = (I + M)^{-1} h */
|
52
|
+
scs_float *lin_sys_warm_start; /* linear system warm-start (indirect only) */
|
53
|
+
scs_float *diag_r; /* vector of R matrix diagonals (affects cone proj) */
|
54
|
+
AaWork *accel; /* struct for acceleration workspace */
|
55
|
+
scs_float *b_orig, *c_orig; /* original b and c vectors */
|
56
|
+
scs_float *b_normalized, *c_normalized; /* normalized b and c vectors */
|
57
|
+
scs_int m, n; /* A has m rows, n cols */
|
58
|
+
ScsMatrix *A; /* (possibly normalized) A matrix */
|
59
|
+
ScsMatrix *P; /* (possibly normalized) P matrix */
|
60
|
+
ScsLinSysWork *p; /* struct populated by linear system solver */
|
61
|
+
ScsScaling *scal; /* contains the re-scaling data */
|
62
|
+
ScsConeWork *cone_work; /* workspace for the cone projection step */
|
63
|
+
/* normalized and unnormalized residuals */
|
64
|
+
ScsResiduals *r_orig, *r_normalized;
|
65
|
+
/* track x,y,s as alg progresses, tau *not* divided out */
|
66
|
+
ScsSolution *xys_orig, *xys_normalized;
|
67
|
+
/* updating scale params workspace */
|
68
|
+
scs_float sum_log_scale_factor;
|
69
|
+
scs_int last_scale_update_iter, n_log_scale_factor, scale_updates;
|
70
|
+
/* aa norm stat */
|
71
|
+
scs_float aa_norm;
|
72
|
+
scs_int rejected_accel_steps, accepted_accel_steps;
|
73
|
+
scs_float setup_time; /* time taken for setup phase (milliseconds) */
|
74
|
+
scs_float scale; /* current scale parameter */
|
75
|
+
const ScsData *d;
|
76
|
+
const ScsCone *k;
|
77
|
+
const ScsSettings *stgs; /* contains solver settings specified by user */
|
78
|
+
};
|
79
|
+
|
80
|
+
#ifdef __cplusplus
|
81
|
+
}
|
82
|
+
#endif
|
83
|
+
#endif
|
@@ -18,10 +18,11 @@ void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
|
|
18
18
|
if (p) {
|
19
19
|
SCS(cs_spfree)(p->L);
|
20
20
|
SCS(cs_spfree)(p->kkt);
|
21
|
+
scs_free(p->diag_p);
|
21
22
|
scs_free(p->perm);
|
22
23
|
scs_free(p->Dinv);
|
23
24
|
scs_free(p->bp);
|
24
|
-
scs_free(p->
|
25
|
+
scs_free(p->diag_r_idxs);
|
25
26
|
scs_free(p->Lnz);
|
26
27
|
scs_free(p->iwork);
|
27
28
|
scs_free(p->etree);
|
@@ -32,9 +33,8 @@ void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
|
|
32
33
|
}
|
33
34
|
}
|
34
35
|
|
35
|
-
static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
36
|
-
scs_float *
|
37
|
-
scs_float rho_x) {
|
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) {
|
38
38
|
/* ONLY UPPER TRIANGULAR PART IS STUFFED
|
39
39
|
* forms column compressed kkt matrix
|
40
40
|
* assumes column compressed form A matrix
|
@@ -42,7 +42,7 @@ static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
|
42
42
|
* forms upper triangular part of [(I + P) A'; A -I]
|
43
43
|
* P : n x n, A: m x n.
|
44
44
|
*/
|
45
|
-
scs_int i, j,
|
45
|
+
scs_int h, i, j, count;
|
46
46
|
csc *Kcsc, *K;
|
47
47
|
scs_int n = A->n;
|
48
48
|
scs_int m = A->m;
|
@@ -65,72 +65,80 @@ static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
|
65
65
|
return SCS_NULL;
|
66
66
|
}
|
67
67
|
|
68
|
-
|
68
|
+
count = 0; /* element counter */
|
69
69
|
if (P) {
|
70
|
-
/*
|
71
|
-
for (j = 0; j <
|
70
|
+
/* R_x + P in top left */
|
71
|
+
for (j = 0; j < n; j++) { /* cols */
|
72
|
+
diag_p[j] = 0.;
|
72
73
|
/* empty column, add diagonal */
|
73
74
|
if (P->p[j] == P->p[j + 1]) {
|
74
|
-
K->i[
|
75
|
-
K->p[
|
76
|
-
K->x[
|
77
|
-
|
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++;
|
78
80
|
}
|
79
|
-
for (
|
80
|
-
i = P->i[
|
81
|
+
for (h = P->p[j]; h < P->p[j + 1]; h++) {
|
82
|
+
i = P->i[h]; /* row */
|
81
83
|
if (i > j) { /* only upper triangular needed */
|
82
84
|
break;
|
83
85
|
}
|
84
|
-
K->i[
|
85
|
-
K->p[
|
86
|
-
K->x[
|
86
|
+
K->i[count] = i;
|
87
|
+
K->p[count] = j;
|
88
|
+
K->x[count] = P->x[h];
|
87
89
|
if (i == j) {
|
88
90
|
/* P has diagonal element */
|
89
|
-
|
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 */
|
90
94
|
}
|
91
|
-
|
95
|
+
count++;
|
92
96
|
/* reached the end without adding diagonal, do it now */
|
93
|
-
if ((i < j) && (
|
94
|
-
K->i[
|
95
|
-
K->p[
|
96
|
-
K->x[
|
97
|
-
|
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++;
|
98
103
|
}
|
99
104
|
}
|
100
105
|
}
|
101
106
|
} else {
|
102
|
-
/*
|
103
|
-
for (
|
104
|
-
|
105
|
-
K->
|
106
|
-
K->
|
107
|
-
|
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++;
|
108
115
|
}
|
109
116
|
}
|
110
117
|
|
111
118
|
/* A^T at top right */
|
112
119
|
for (j = 0; j < n; j++) {
|
113
|
-
for (
|
114
|
-
K->p[
|
115
|
-
K->i[
|
116
|
-
K->x[
|
117
|
-
|
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++;
|
118
125
|
}
|
119
126
|
}
|
120
127
|
|
121
|
-
/* -
|
122
|
-
for (
|
123
|
-
K->i[
|
124
|
-
K->p[
|
125
|
-
K->x[
|
126
|
-
|
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++;
|
128
135
|
}
|
129
|
-
|
130
|
-
|
136
|
+
|
137
|
+
K->nz = count;
|
138
|
+
idx_mapping = (scs_int *)scs_calloc(K->nz, sizeof(scs_int));
|
131
139
|
Kcsc = SCS(cs_compress)(K, idx_mapping);
|
132
|
-
for (i = 0; i <
|
133
|
-
|
140
|
+
for (i = 0; i < m + n; i++) {
|
141
|
+
diag_r_idxs[i] = idx_mapping[diag_r_idxs[i]];
|
134
142
|
}
|
135
143
|
SCS(cs_spfree)(K);
|
136
144
|
scs_free(idx_mapping);
|
@@ -138,7 +146,7 @@ static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
|
138
146
|
}
|
139
147
|
|
140
148
|
static scs_int _ldl_init(csc *A, scs_int *P, scs_float **info) {
|
141
|
-
*info = (scs_float *)
|
149
|
+
*info = (scs_float *)scs_calloc(AMD_INFO, sizeof(scs_float));
|
142
150
|
return amd_order(A->n, A->p, A->i, P, (scs_float *)SCS_NULL, *info);
|
143
151
|
}
|
144
152
|
|
@@ -146,10 +154,10 @@ static scs_int _ldl_init(csc *A, scs_int *P, scs_float **info) {
|
|
146
154
|
static scs_int ldl_prepare(ScsLinSysWork *p) {
|
147
155
|
csc *kkt = p->kkt, *L = p->L;
|
148
156
|
scs_int n = kkt->n;
|
149
|
-
p->etree = (scs_int *)
|
150
|
-
p->Lnz = (scs_int *)
|
151
|
-
p->iwork = (scs_int *)
|
152
|
-
L->p = (scs_int *)
|
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));
|
153
161
|
L->nzmax = QDLDL_etree(n, kkt->p, kkt->i, p->iwork, p->Lnz, p->etree);
|
154
162
|
if (L->nzmax < 0) {
|
155
163
|
scs_printf("Error in elimination tree calculation.\n");
|
@@ -161,12 +169,12 @@ static scs_int ldl_prepare(ScsLinSysWork *p) {
|
|
161
169
|
return L->nzmax;
|
162
170
|
}
|
163
171
|
|
164
|
-
L->x = (scs_float *)
|
165
|
-
L->i = (scs_int *)
|
166
|
-
p->Dinv = (scs_float *)
|
167
|
-
p->D = (scs_float *)
|
168
|
-
p->bwork = (scs_int *)
|
169
|
-
p->fwork = (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));
|
170
178
|
return L->nzmax;
|
171
179
|
}
|
172
180
|
|
@@ -223,7 +231,7 @@ static scs_int *cs_pinv(scs_int const *p, scs_int n) {
|
|
223
231
|
if (!p) {
|
224
232
|
return SCS_NULL;
|
225
233
|
} /* p = SCS_NULL denotes identity */
|
226
|
-
pinv = (scs_int *)
|
234
|
+
pinv = (scs_int *)scs_calloc(n, sizeof(scs_int)); /* allocate result */
|
227
235
|
if (!pinv) {
|
228
236
|
return SCS_NULL;
|
229
237
|
} /* out of memory */
|
@@ -283,10 +291,10 @@ static csc *cs_symperm(const csc *A, const scs_int *pinv, scs_int *idx_mapping,
|
|
283
291
|
}
|
284
292
|
|
285
293
|
static csc *permute_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
286
|
-
ScsLinSysWork *p, scs_float *
|
294
|
+
ScsLinSysWork *p, const scs_float *diag_r) {
|
287
295
|
scs_float *info;
|
288
296
|
scs_int *Pinv, amd_status, *idx_mapping, i;
|
289
|
-
csc *kkt_perm, *kkt = form_kkt(A, P,
|
297
|
+
csc *kkt_perm, *kkt = form_kkt(A, P, p->diag_p, diag_r, p->diag_r_idxs);
|
290
298
|
if (!kkt) {
|
291
299
|
return SCS_NULL;
|
292
300
|
}
|
@@ -300,10 +308,10 @@ static csc *permute_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
|
300
308
|
amd_info(info);
|
301
309
|
#endif
|
302
310
|
Pinv = cs_pinv(p->perm, A->n + A->m);
|
303
|
-
idx_mapping = (scs_int *)
|
311
|
+
idx_mapping = (scs_int *)scs_calloc(kkt->nzmax, sizeof(scs_int));
|
304
312
|
kkt_perm = cs_symperm(kkt, Pinv, idx_mapping, 1);
|
305
|
-
for (i = 0; i < A->m; i++) {
|
306
|
-
p->
|
313
|
+
for (i = 0; i < A->n + A->m; i++) {
|
314
|
+
p->diag_r_idxs[i] = idx_mapping[p->diag_r_idxs[i]];
|
307
315
|
}
|
308
316
|
SCS(cs_spfree)(kkt);
|
309
317
|
scs_free(Pinv);
|
@@ -312,10 +320,15 @@ static csc *permute_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
|
312
320
|
return kkt_perm;
|
313
321
|
}
|
314
322
|
|
315
|
-
void SCS(
|
323
|
+
void SCS(update_lin_sys_diag_r)(ScsLinSysWork *p, const scs_float *diag_r) {
|
316
324
|
scs_int i, ldl_status;
|
317
|
-
for (i = 0; i < p->
|
318
|
-
|
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];
|
319
332
|
}
|
320
333
|
ldl_status = ldl_factor(p, p->n);
|
321
334
|
if (ldl_status < 0) {
|
@@ -327,21 +340,21 @@ void SCS(update_lin_sys_rho_y_vec)(ScsLinSysWork *p, scs_float *rho_y_vec) {
|
|
327
340
|
}
|
328
341
|
|
329
342
|
ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
|
330
|
-
scs_float *
|
343
|
+
const scs_float *diag_r) {
|
331
344
|
ScsLinSysWork *p = (ScsLinSysWork *)scs_calloc(1, sizeof(ScsLinSysWork));
|
332
345
|
scs_int n_plus_m = A->n + A->m, ldl_status, ldl_prepare_status;
|
333
346
|
p->m = A->m;
|
334
347
|
p->n = A->n;
|
335
|
-
p->
|
336
|
-
p->perm = (scs_int *)
|
337
|
-
p->L = (csc *)
|
338
|
-
p->bp = (scs_float *)
|
339
|
-
p->
|
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));
|
340
353
|
p->factorizations = 0;
|
341
354
|
p->L->m = n_plus_m;
|
342
355
|
p->L->n = n_plus_m;
|
343
356
|
p->L->nz = -1;
|
344
|
-
p->kkt = permute_kkt(A, P, p,
|
357
|
+
p->kkt = permute_kkt(A, P, p, diag_r);
|
345
358
|
ldl_prepare_status = ldl_prepare(p);
|
346
359
|
ldl_status = ldl_factor(p, A->n);
|
347
360
|
if (ldl_prepare_status < 0 || ldl_status < 0) {
|
@@ -18,12 +18,12 @@ struct SCS_LIN_SYS_WORK {
|
|
18
18
|
scs_float *Dinv; /* inverse diagonal matrix of factorization */
|
19
19
|
scs_int *perm; /* permutation of KKT matrix for factorization */
|
20
20
|
scs_float *bp; /* workspace memory for solves */
|
21
|
-
scs_int *
|
21
|
+
scs_int *diag_r_idxs;
|
22
22
|
scs_int factorizations;
|
23
23
|
/* ldl factorization workspace */
|
24
24
|
scs_float *D, *fwork;
|
25
25
|
scs_int *etree, *iwork, *Lnz, *bwork;
|
26
|
-
scs_float
|
26
|
+
scs_float *diag_p;
|
27
27
|
};
|
28
28
|
|
29
29
|
#ifdef __cplusplus
|