scs 0.2.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 +7 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +84 -0
- data/ext/scs/Rakefile +11 -0
- data/lib/scs/ffi.rb +117 -0
- data/lib/scs/solver.rb +178 -0
- data/lib/scs/version.rb +3 -0
- data/lib/scs.rb +17 -0
- data/vendor/scs/LICENSE.txt +21 -0
- data/vendor/scs/Makefile +164 -0
- data/vendor/scs/README.md +220 -0
- data/vendor/scs/include/aa.h +56 -0
- data/vendor/scs/include/cones.h +46 -0
- data/vendor/scs/include/ctrlc.h +33 -0
- data/vendor/scs/include/glbopts.h +177 -0
- data/vendor/scs/include/linalg.h +26 -0
- data/vendor/scs/include/linsys.h +64 -0
- data/vendor/scs/include/normalize.h +18 -0
- data/vendor/scs/include/rw.h +17 -0
- data/vendor/scs/include/scs.h +161 -0
- data/vendor/scs/include/scs_blas.h +51 -0
- data/vendor/scs/include/util.h +65 -0
- data/vendor/scs/linsys/amatrix.c +305 -0
- data/vendor/scs/linsys/amatrix.h +36 -0
- data/vendor/scs/linsys/amatrix.o +0 -0
- data/vendor/scs/linsys/cpu/direct/private.c +366 -0
- data/vendor/scs/linsys/cpu/direct/private.h +26 -0
- data/vendor/scs/linsys/cpu/direct/private.o +0 -0
- data/vendor/scs/linsys/cpu/indirect/private.c +256 -0
- data/vendor/scs/linsys/cpu/indirect/private.h +31 -0
- data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
- data/vendor/scs/linsys/external/amd/LICENSE.txt +934 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +469 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +254 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
- data/vendor/scs/linsys/external/amd/amd.h +400 -0
- data/vendor/scs/linsys/external/amd/amd_1.c +180 -0
- data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_2.c +1842 -0
- data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_aat.c +184 -0
- data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_control.c +64 -0
- data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_defaults.c +37 -0
- data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_dump.c +179 -0
- data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_global.c +16 -0
- data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_info.c +119 -0
- data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_internal.h +304 -0
- data/vendor/scs/linsys/external/amd/amd_order.c +199 -0
- data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_post_tree.c +120 -0
- data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_postorder.c +206 -0
- data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_preprocess.c +118 -0
- data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_valid.c +92 -0
- data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
- data/vendor/scs/linsys/external/amd/changes +11 -0
- data/vendor/scs/linsys/external/qdldl/LICENSE +201 -0
- data/vendor/scs/linsys/external/qdldl/README.md +120 -0
- data/vendor/scs/linsys/external/qdldl/changes +4 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.c +298 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.h +177 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
- data/vendor/scs/linsys/external/qdldl/qdldl_types.h +21 -0
- data/vendor/scs/linsys/gpu/gpu.c +41 -0
- data/vendor/scs/linsys/gpu/gpu.h +85 -0
- data/vendor/scs/linsys/gpu/indirect/private.c +304 -0
- data/vendor/scs/linsys/gpu/indirect/private.h +36 -0
- data/vendor/scs/scs.mk +181 -0
- data/vendor/scs/src/aa.c +224 -0
- data/vendor/scs/src/aa.o +0 -0
- data/vendor/scs/src/cones.c +802 -0
- data/vendor/scs/src/cones.o +0 -0
- data/vendor/scs/src/ctrlc.c +77 -0
- data/vendor/scs/src/ctrlc.o +0 -0
- data/vendor/scs/src/linalg.c +84 -0
- data/vendor/scs/src/linalg.o +0 -0
- data/vendor/scs/src/normalize.c +93 -0
- data/vendor/scs/src/normalize.o +0 -0
- data/vendor/scs/src/rw.c +167 -0
- data/vendor/scs/src/rw.o +0 -0
- data/vendor/scs/src/scs.c +975 -0
- data/vendor/scs/src/scs.o +0 -0
- data/vendor/scs/src/scs_version.c +5 -0
- data/vendor/scs/src/scs_version.o +0 -0
- data/vendor/scs/src/util.c +196 -0
- data/vendor/scs/src/util.o +0 -0
- data/vendor/scs/test/data/small_random_socp +0 -0
- data/vendor/scs/test/minunit.h +13 -0
- data/vendor/scs/test/problem_utils.h +93 -0
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +85 -0
- data/vendor/scs/test/problems/small_lp.h +50 -0
- data/vendor/scs/test/problems/small_random_socp.h +33 -0
- data/vendor/scs/test/random_socp_prob.c +171 -0
- data/vendor/scs/test/run_from_file.c +69 -0
- data/vendor/scs/test/run_tests +2 -0
- data/vendor/scs/test/run_tests.c +32 -0
- metadata +203 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#ifndef SCS_H_GUARD
|
|
2
|
+
#define SCS_H_GUARD
|
|
3
|
+
|
|
4
|
+
#ifdef __cplusplus
|
|
5
|
+
extern "C" {
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
#include <string.h>
|
|
9
|
+
#include "glbopts.h"
|
|
10
|
+
#include "aa.h"
|
|
11
|
+
|
|
12
|
+
/* private data structs (that you define) containing any necessary data to solve
|
|
13
|
+
* linear system, etc. this defines the matrix A, only the linear system solver
|
|
14
|
+
* interacts with this struct */
|
|
15
|
+
typedef struct SCS_A_DATA_MATRIX ScsMatrix;
|
|
16
|
+
/* stores the necessary private workspace, only the linear system solver
|
|
17
|
+
* interacts with this struct */
|
|
18
|
+
typedef struct SCS_LIN_SYS_WORK ScsLinSysWork;
|
|
19
|
+
|
|
20
|
+
typedef struct SCS_PROBLEM_DATA ScsData;
|
|
21
|
+
typedef struct SCS_SETTINGS ScsSettings;
|
|
22
|
+
typedef struct SCS_SOL_VARS ScsSolution;
|
|
23
|
+
typedef struct SCS_INFO ScsInfo;
|
|
24
|
+
typedef struct SCS_SCALING ScsScaling;
|
|
25
|
+
typedef struct SCS_WORK ScsWork;
|
|
26
|
+
typedef struct SCS_RESIDUALS ScsResiduals;
|
|
27
|
+
typedef struct SCS_CONE ScsCone;
|
|
28
|
+
typedef struct SCS_ACCEL_WORK ScsAccelWork;
|
|
29
|
+
typedef struct SCS_CONE_WORK ScsConeWork;
|
|
30
|
+
|
|
31
|
+
/* struct containing problem data */
|
|
32
|
+
struct SCS_PROBLEM_DATA {
|
|
33
|
+
/* these cannot change for multiple runs for the same call to SCS(init) */
|
|
34
|
+
scs_int m, n; /* A has m rows, n cols */
|
|
35
|
+
ScsMatrix *A; /* A is supplied in data format specified by linsys solver */
|
|
36
|
+
|
|
37
|
+
/* these can change for multiple runs for the same call to SCS(init) */
|
|
38
|
+
scs_float *b, *c; /* dense arrays for b (size m), c (size n) */
|
|
39
|
+
|
|
40
|
+
ScsSettings *stgs; /* contains solver settings specified by user */
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/* ScsSettings struct */
|
|
44
|
+
struct SCS_SETTINGS {
|
|
45
|
+
/* settings parameters: default suggested input */
|
|
46
|
+
|
|
47
|
+
/* these *cannot* change for multiple runs with the same call to SCS(init) */
|
|
48
|
+
scs_int normalize; /* boolean, heuristic data rescaling: 1 */
|
|
49
|
+
scs_float scale; /* if normalized, rescales by this factor: 5 */
|
|
50
|
+
scs_float rho_x; /* x equality constraint scaling: 1e-3 */
|
|
51
|
+
|
|
52
|
+
/* these can change for multiple runs with the same call to SCS(init) */
|
|
53
|
+
scs_int max_iters; /* maximum iterations to take: 2500 */
|
|
54
|
+
scs_float eps; /* convergence tolerance: 1e-3 */
|
|
55
|
+
scs_float alpha; /* relaxation parameter: 1.8 */
|
|
56
|
+
scs_float cg_rate; /* for indirect, tolerance goes down like
|
|
57
|
+
(1/iter)^cg_rate: 2 */
|
|
58
|
+
scs_int verbose; /* boolean, write out progress: 1 */
|
|
59
|
+
scs_int warm_start; /* boolean, warm start (put initial guess in ScsSolution
|
|
60
|
+
struct): 0 */
|
|
61
|
+
scs_int acceleration_lookback; /* memory for acceleration */
|
|
62
|
+
const char* write_data_filename; /* string, if set will dump data */
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/* NB: rows of data matrix A must be specified in this exact order */
|
|
66
|
+
struct SCS_CONE {
|
|
67
|
+
scs_int f; /* number of linear equality constraints */
|
|
68
|
+
scs_int l; /* length of LP cone */
|
|
69
|
+
scs_int *q; /* array of second-order cone constraints */
|
|
70
|
+
scs_int qsize; /* length of SOC array */
|
|
71
|
+
scs_int *s; /* array of SD constraints */
|
|
72
|
+
scs_int ssize; /* length of SD array */
|
|
73
|
+
scs_int ep; /* number of primal exponential cone triples */
|
|
74
|
+
scs_int ed; /* number of dual exponential cone triples */
|
|
75
|
+
scs_float *p; /* array of power cone params, must be \in [-1, 1],
|
|
76
|
+
negative values are interpreted as specifying the
|
|
77
|
+
dual cone */
|
|
78
|
+
scs_int psize; /* number of (primal and dual) power cone triples */
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/* contains primal-dual solution arrays */
|
|
82
|
+
struct SCS_SOL_VARS {
|
|
83
|
+
scs_float *x, *y, *s;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/* contains terminating information */
|
|
87
|
+
struct SCS_INFO {
|
|
88
|
+
scs_int iter; /* number of iterations taken */
|
|
89
|
+
char status[32]; /* status string, e.g. 'Solved' */
|
|
90
|
+
scs_int status_val; /* status as scs_int, defined in glbopts.h */
|
|
91
|
+
scs_float pobj; /* primal objective */
|
|
92
|
+
scs_float dobj; /* dual objective */
|
|
93
|
+
scs_float res_pri; /* primal equality residual */
|
|
94
|
+
scs_float res_dual; /* dual equality residual */
|
|
95
|
+
scs_float res_infeas; /* infeasibility cert residual */
|
|
96
|
+
scs_float res_unbdd; /* unbounded cert residual */
|
|
97
|
+
scs_float rel_gap; /* relative duality gap */
|
|
98
|
+
scs_float setup_time; /* time taken for setup phase (milliseconds) */
|
|
99
|
+
scs_float solve_time; /* time taken for solve phase (milliseconds) */
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/* contains normalization variables */
|
|
103
|
+
struct SCS_SCALING {
|
|
104
|
+
scs_float *D, *E; /* for normalization */
|
|
105
|
+
scs_float mean_norm_row_a, mean_norm_col_a;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/*
|
|
109
|
+
* main library api's:
|
|
110
|
+
* SCS(init): allocates memory etc (e.g., factorize matrix [I A; A^T -I])
|
|
111
|
+
* SCS(solve): can be called many times with different b,c data per init call
|
|
112
|
+
* SCS(finish): cleans up the memory (one per init call)
|
|
113
|
+
*/
|
|
114
|
+
ScsWork *SCS(init)(const ScsData *d, const ScsCone *k, ScsInfo *info);
|
|
115
|
+
scs_int SCS(solve)(ScsWork *w, const ScsData *d, const ScsCone *k,
|
|
116
|
+
ScsSolution *sol, ScsInfo *info);
|
|
117
|
+
void SCS(finish)(ScsWork *w);
|
|
118
|
+
/* scs calls SCS(init), SCS(solve), and SCS(finish) */
|
|
119
|
+
scs_int scs(const ScsData *d, const ScsCone *k, ScsSolution *sol,
|
|
120
|
+
ScsInfo *info);
|
|
121
|
+
|
|
122
|
+
const char *SCS(version)(void);
|
|
123
|
+
size_t SCS(sizeof_int)(void);
|
|
124
|
+
size_t SCS(sizeof_float)(void);
|
|
125
|
+
|
|
126
|
+
/* the following structs are not exposed to user */
|
|
127
|
+
|
|
128
|
+
/* workspace for SCS */
|
|
129
|
+
struct SCS_WORK {
|
|
130
|
+
/* x_prev = x from previous iteration */
|
|
131
|
+
scs_float *u, *u_best, *v, *v_best, *u_t, *u_prev, *v_prev;
|
|
132
|
+
scs_float *h, *g, *pr, *dr;
|
|
133
|
+
scs_float g_th, sc_b, sc_c, nm_b, nm_c, best_max_residual;
|
|
134
|
+
scs_float *b, *c; /* (possibly normalized) b and c vectors */
|
|
135
|
+
scs_int m, n; /* A has m rows, n cols */
|
|
136
|
+
ScsMatrix *A; /* (possibly normalized) A matrix */
|
|
137
|
+
ScsLinSysWork *p; /* struct populated by linear system solver */
|
|
138
|
+
ScsSettings *stgs; /* contains solver settings specified by user */
|
|
139
|
+
ScsScaling *scal; /* contains the re-scaling data */
|
|
140
|
+
ScsConeWork *cone_work; /* workspace for the cone projection step */
|
|
141
|
+
AaWork *accel; /* Struct for acceleration workspace */
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/* to hold residual information (unnormalized) */
|
|
145
|
+
struct SCS_RESIDUALS {
|
|
146
|
+
scs_int last_iter;
|
|
147
|
+
scs_float res_dual;
|
|
148
|
+
scs_float res_pri;
|
|
149
|
+
scs_float res_infeas;
|
|
150
|
+
scs_float res_unbdd;
|
|
151
|
+
scs_float rel_gap;
|
|
152
|
+
scs_float ct_x_by_tau; /* not divided by tau */
|
|
153
|
+
scs_float bt_y_by_tau; /* not divided by tau */
|
|
154
|
+
scs_float tau;
|
|
155
|
+
scs_float kap;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
#ifdef __cplusplus
|
|
159
|
+
}
|
|
160
|
+
#endif
|
|
161
|
+
#endif
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#ifndef SCS_BLAS_H_GUARD
|
|
2
|
+
#define SCS_BLAS_H_GUARD
|
|
3
|
+
|
|
4
|
+
#ifdef USE_LAPACK
|
|
5
|
+
|
|
6
|
+
#ifdef __cplusplus
|
|
7
|
+
extern "C" {
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
/* Default to underscore for blas / lapack */
|
|
11
|
+
#ifndef BLASSUFFIX
|
|
12
|
+
#define BLASSUFFIX _
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
/* annoying hack because some preprocessors can't handle empty macros */
|
|
16
|
+
#if defined(NOBLASSUFFIX) && NOBLASSUFFIX > 0
|
|
17
|
+
/* single or double precision */
|
|
18
|
+
#ifndef SFLOAT
|
|
19
|
+
#define BLAS(x) d##x
|
|
20
|
+
#else
|
|
21
|
+
#define BLAS(x) s##x
|
|
22
|
+
#endif
|
|
23
|
+
#else
|
|
24
|
+
/* this extra indirection is needed for BLASSUFFIX to work correctly as a
|
|
25
|
+
* variable */
|
|
26
|
+
#define stitch_(pre, x, post) pre##x##post
|
|
27
|
+
#define stitch__(pre, x, post) stitch_(pre, x, post)
|
|
28
|
+
/* single or double precision */
|
|
29
|
+
#ifndef SFLOAT
|
|
30
|
+
#define BLAS(x) stitch__(d, x, BLASSUFFIX)
|
|
31
|
+
#else
|
|
32
|
+
#define BLAS(x) stitch__(s, x, BLASSUFFIX)
|
|
33
|
+
#endif
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
#ifdef MATLAB_MEX_FILE
|
|
37
|
+
typedef ptrdiff_t blas_int;
|
|
38
|
+
#elif defined BLAS64
|
|
39
|
+
#include <stdint.h>
|
|
40
|
+
typedef int64_t blas_int;
|
|
41
|
+
#else
|
|
42
|
+
typedef int blas_int;
|
|
43
|
+
#endif
|
|
44
|
+
|
|
45
|
+
#ifdef __cplusplus
|
|
46
|
+
}
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
#endif /* USE_LAPACK */
|
|
50
|
+
|
|
51
|
+
#endif /* SCS_BLAS_H_GUARD */
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#ifndef UTIL_H_GUARD
|
|
2
|
+
#define UTIL_H_GUARD
|
|
3
|
+
|
|
4
|
+
#ifdef __cplusplus
|
|
5
|
+
extern "C" {
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
#include <stdio.h>
|
|
9
|
+
#include <stdlib.h>
|
|
10
|
+
#include "cones.h"
|
|
11
|
+
#include "scs.h"
|
|
12
|
+
|
|
13
|
+
/* timing code courtesy of A. Domahidi */
|
|
14
|
+
#if (defined NOTIMER)
|
|
15
|
+
typedef void *SCS(timer);
|
|
16
|
+
#elif (defined _WIN32 || defined _WIN64 || defined _WINDLL)
|
|
17
|
+
/* Use Windows QueryPerformanceCounter for timing */
|
|
18
|
+
#include <windows.h>
|
|
19
|
+
typedef struct SCS(timer) {
|
|
20
|
+
LARGE_INTEGER tic;
|
|
21
|
+
LARGE_INTEGER toc;
|
|
22
|
+
LARGE_INTEGER freq;
|
|
23
|
+
} SCS(timer);
|
|
24
|
+
|
|
25
|
+
#elif (defined __APPLE__)
|
|
26
|
+
/* Use MAC OSX mach_time for timing */
|
|
27
|
+
#include <mach/mach_time.h>
|
|
28
|
+
typedef struct SCS(timer) {
|
|
29
|
+
uint64_t tic;
|
|
30
|
+
uint64_t toc;
|
|
31
|
+
mach_timebase_info_data_t tinfo;
|
|
32
|
+
} SCS(timer);
|
|
33
|
+
|
|
34
|
+
#else
|
|
35
|
+
/* Use POSIX clock_gettime() for timing on other machines */
|
|
36
|
+
#include <time.h>
|
|
37
|
+
typedef struct SCS(timer) {
|
|
38
|
+
struct timespec tic;
|
|
39
|
+
struct timespec toc;
|
|
40
|
+
} SCS(timer);
|
|
41
|
+
|
|
42
|
+
#endif
|
|
43
|
+
|
|
44
|
+
#if EXTRA_VERBOSE > 1
|
|
45
|
+
extern SCS(timer) global_timer;
|
|
46
|
+
#endif
|
|
47
|
+
|
|
48
|
+
/* these all return milli-seconds */
|
|
49
|
+
void SCS(tic)(SCS(timer) * t);
|
|
50
|
+
scs_float SCS(toc)(SCS(timer) * t);
|
|
51
|
+
scs_float SCS(str_toc)(char *str, SCS(timer) * t);
|
|
52
|
+
scs_float SCS(tocq)(SCS(timer) * t);
|
|
53
|
+
|
|
54
|
+
void SCS(print_cone_data)(const ScsCone *k);
|
|
55
|
+
void SCS(print_data)(const ScsData *d);
|
|
56
|
+
void SCS(print_work)(const ScsWork *w);
|
|
57
|
+
void SCS(print_array)(const scs_float *arr, scs_int n, const char *name);
|
|
58
|
+
void SCS(set_default_settings)(ScsData *d);
|
|
59
|
+
void SCS(free_sol)(ScsSolution *sol);
|
|
60
|
+
void SCS(free_data)(ScsData *d, ScsCone *k);
|
|
61
|
+
|
|
62
|
+
#ifdef __cplusplus
|
|
63
|
+
}
|
|
64
|
+
#endif
|
|
65
|
+
#endif
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/* contains routines common to direct and indirect sparse solvers */
|
|
2
|
+
#include "amatrix.h"
|
|
3
|
+
|
|
4
|
+
#include "linsys.h"
|
|
5
|
+
|
|
6
|
+
#define MIN_SCALE (1e-4)
|
|
7
|
+
#define MAX_SCALE (1e4)
|
|
8
|
+
#define NUM_SCALE_PASSES 10 /* additional passes don't help much */
|
|
9
|
+
|
|
10
|
+
scs_int SCS(copy_a_matrix)(ScsMatrix **dstp, const ScsMatrix *src) {
|
|
11
|
+
scs_int Anz = src->p[src->n];
|
|
12
|
+
ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
13
|
+
if (!A) {
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
A->n = src->n;
|
|
17
|
+
A->m = src->m;
|
|
18
|
+
A->x = (scs_float *)scs_malloc(sizeof(scs_float) *
|
|
19
|
+
Anz); /* A values, size: NNZ A */
|
|
20
|
+
A->i = (scs_int *)scs_malloc(sizeof(scs_int) *
|
|
21
|
+
Anz); /* A row index, size: NNZ A */
|
|
22
|
+
A->p = (scs_int *)scs_malloc(sizeof(scs_int) *
|
|
23
|
+
(src->n + 1)); /* A column pointer, size: n+1 */
|
|
24
|
+
if (!A->x || !A->i || !A->p) {
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
memcpy(A->x, src->x, sizeof(scs_float) * Anz);
|
|
28
|
+
memcpy(A->i, src->i, sizeof(scs_int) * Anz);
|
|
29
|
+
memcpy(A->p, src->p, sizeof(scs_int) * (src->n + 1));
|
|
30
|
+
*dstp = A;
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
scs_int SCS(validate_lin_sys)(const ScsMatrix *A) {
|
|
35
|
+
scs_int i, r_max, Anz;
|
|
36
|
+
if (!A->x || !A->i || !A->p) {
|
|
37
|
+
scs_printf("data incompletely specified\n");
|
|
38
|
+
return -1;
|
|
39
|
+
}
|
|
40
|
+
/* detects some errors in A col ptrs: */
|
|
41
|
+
Anz = A->p[A->n];
|
|
42
|
+
if (Anz > 0) {
|
|
43
|
+
for (i = 0; i < A->n; ++i) {
|
|
44
|
+
if (A->p[i] == A->p[i + 1]) {
|
|
45
|
+
scs_printf(
|
|
46
|
+
"WARN: A->p (column pointers) not strictly increasing, "
|
|
47
|
+
"column %li empty\n",
|
|
48
|
+
(long)i);
|
|
49
|
+
} else if (A->p[i] > A->p[i + 1]) {
|
|
50
|
+
scs_printf("ERROR: A->p (column pointers) decreasing\n");
|
|
51
|
+
return -1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (((scs_float)Anz / A->m > A->n) || (Anz < 0)) {
|
|
56
|
+
scs_printf("Anz (nonzeros in A) = %li, outside of valid range\n",
|
|
57
|
+
(long)Anz);
|
|
58
|
+
return -1;
|
|
59
|
+
}
|
|
60
|
+
r_max = 0;
|
|
61
|
+
for (i = 0; i < Anz; ++i) {
|
|
62
|
+
if (A->i[i] > r_max) {
|
|
63
|
+
r_max = A->i[i];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (r_max > A->m - 1) {
|
|
67
|
+
scs_printf("number of rows in A inconsistent with input dimension\n");
|
|
68
|
+
return -1;
|
|
69
|
+
}
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
void SCS(free_a_matrix)(ScsMatrix *A) {
|
|
74
|
+
if (A) {
|
|
75
|
+
scs_free(A->x);
|
|
76
|
+
scs_free(A->i);
|
|
77
|
+
scs_free(A->p);
|
|
78
|
+
scs_free(A);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#if EXTRA_VERBOSE > 0
|
|
83
|
+
static void print_a_matrix(const ScsMatrix *A) {
|
|
84
|
+
scs_int i, j;
|
|
85
|
+
/* TODO: this is to prevent clogging stdout */
|
|
86
|
+
if (A->p[A->n] < 2500) {
|
|
87
|
+
scs_printf("\n");
|
|
88
|
+
for (i = 0; i < A->n; ++i) {
|
|
89
|
+
scs_printf("Col %li: ", (long)i);
|
|
90
|
+
for (j = A->p[i]; j < A->p[i + 1]; j++) {
|
|
91
|
+
scs_printf("A[%li,%li] = %4f, ", (long)A->i[j], (long)i, A->x[j]);
|
|
92
|
+
}
|
|
93
|
+
scs_printf("norm col = %4f\n",
|
|
94
|
+
SCS(norm)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]));
|
|
95
|
+
}
|
|
96
|
+
scs_printf("norm A = %4f\n", SCS(norm)(A->x, A->p[A->n]));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
#endif
|
|
100
|
+
|
|
101
|
+
void SCS(_normalize_a)(ScsMatrix *A, const ScsSettings *stgs, const ScsCone *k,
|
|
102
|
+
ScsScaling *scal) {
|
|
103
|
+
scs_float *D = (scs_float *)scs_malloc(A->m * sizeof(scs_float));
|
|
104
|
+
scs_float *E = (scs_float *)scs_malloc(A->n * sizeof(scs_float));
|
|
105
|
+
scs_float *Dt = (scs_float *)scs_malloc(A->m * sizeof(scs_float));
|
|
106
|
+
scs_float *Et = (scs_float *)scs_malloc(A->n * sizeof(scs_float));
|
|
107
|
+
scs_float *nms = (scs_float *)scs_calloc(A->m, sizeof(scs_float));
|
|
108
|
+
scs_int i, j, l, count, delta, *boundaries;
|
|
109
|
+
scs_int num_boundaries = SCS(get_cone_boundaries)(k, &boundaries);
|
|
110
|
+
scs_float wrk;
|
|
111
|
+
|
|
112
|
+
#if EXTRA_VERBOSE > 0
|
|
113
|
+
SCS(timer) normalize_timer;
|
|
114
|
+
SCS(tic)(&normalize_timer);
|
|
115
|
+
scs_printf("normalizing A\n");
|
|
116
|
+
print_a_matrix(A);
|
|
117
|
+
#endif
|
|
118
|
+
|
|
119
|
+
for (l = 0; l < NUM_SCALE_PASSES; ++l) {
|
|
120
|
+
memset(D, 0, A->m * sizeof(scs_float));
|
|
121
|
+
memset(E, 0, A->n * sizeof(scs_float));
|
|
122
|
+
/* calculate row norms */
|
|
123
|
+
for (i = 0; i < A->n; ++i) {
|
|
124
|
+
for (j = A->p[i]; j < A->p[i + 1]; ++j) {
|
|
125
|
+
D[A->i[j]] = MAX(D[A->i[j]], ABS(A->x[j]));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
for (i = 0; i < A->m; ++i) {
|
|
129
|
+
D[i] = SQRTF(D[i]);
|
|
130
|
+
D[i] = D[i] < MIN_SCALE ? 1.0 : D[i];
|
|
131
|
+
D[i] = D[i] > MAX_SCALE ? MAX_SCALE : D[i];
|
|
132
|
+
}
|
|
133
|
+
/* calculate col norms, E */
|
|
134
|
+
for (i = 0; i < A->n; ++i) {
|
|
135
|
+
E[i] = SCS(norm_inf)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]);
|
|
136
|
+
E[i] = SQRTF(E[i]);
|
|
137
|
+
E[i] = E[i] < MIN_SCALE ? 1.0 : E[i];
|
|
138
|
+
E[i] = E[i] > MAX_SCALE ? MAX_SCALE : E[i];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* mean of D across each cone */
|
|
142
|
+
count = boundaries[0];
|
|
143
|
+
for (i = 1; i < num_boundaries; ++i) {
|
|
144
|
+
wrk = 0;
|
|
145
|
+
delta = boundaries[i];
|
|
146
|
+
for (j = count; j < count + delta; ++j) {
|
|
147
|
+
wrk += D[j];
|
|
148
|
+
}
|
|
149
|
+
wrk /= delta;
|
|
150
|
+
for (j = count; j < count + delta; ++j) {
|
|
151
|
+
D[j] = wrk;
|
|
152
|
+
}
|
|
153
|
+
count += delta;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* scale the rows with D */
|
|
157
|
+
for (i = 0; i < A->n; ++i) {
|
|
158
|
+
for (j = A->p[i]; j < A->p[i + 1]; ++j) {
|
|
159
|
+
A->x[j] /= D[A->i[j]];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* scale the cols with E */
|
|
164
|
+
for (i = 0; i < A->n; ++i) {
|
|
165
|
+
SCS(scale_array)(&(A->x[A->p[i]]), 1.0 / E[i], A->p[i + 1] - A->p[i]);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* Accumulate scaling */
|
|
169
|
+
for (i = 0; i < A->m; ++i) {
|
|
170
|
+
Dt[i] = (l == 0) ? D[i] : Dt[i] * D[i];
|
|
171
|
+
}
|
|
172
|
+
for (i = 0; i < A->n; ++i) {
|
|
173
|
+
Et[i] = (l == 0) ? E[i] : Et[i] * E[i];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
scs_free(boundaries);
|
|
177
|
+
scs_free(D);
|
|
178
|
+
scs_free(E);
|
|
179
|
+
|
|
180
|
+
/* calculate mean of row norms of A */
|
|
181
|
+
for (i = 0; i < A->n; ++i) {
|
|
182
|
+
for (j = A->p[i]; j < A->p[i + 1]; ++j) {
|
|
183
|
+
wrk = A->x[j];
|
|
184
|
+
nms[A->i[j]] += wrk * wrk;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
scal->mean_norm_row_a = 0.0;
|
|
188
|
+
for (i = 0; i < A->m; ++i) {
|
|
189
|
+
scal->mean_norm_row_a += SQRTF(nms[i]) / A->m;
|
|
190
|
+
}
|
|
191
|
+
scs_free(nms);
|
|
192
|
+
|
|
193
|
+
/* calculate mean of col norms of A */
|
|
194
|
+
scal->mean_norm_col_a = 0.0;
|
|
195
|
+
for (i = 0; i < A->n; ++i) {
|
|
196
|
+
scal->mean_norm_col_a +=
|
|
197
|
+
SCS(norm)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]) / A->n;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* scale up by d->SCALE if not equal to 1 */
|
|
201
|
+
if (stgs->scale != 1) {
|
|
202
|
+
SCS(scale_array)(A->x, stgs->scale, A->p[A->n]);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
scal->D = Dt;
|
|
206
|
+
scal->E = Et;
|
|
207
|
+
|
|
208
|
+
#if EXTRA_VERBOSE > 0
|
|
209
|
+
scs_printf("finished normalizing A, time: %1.2es\n",
|
|
210
|
+
SCS(tocq)(&normalize_timer) / 1e3);
|
|
211
|
+
print_a_matrix(A);
|
|
212
|
+
#endif
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
void SCS(_un_normalize_a)(ScsMatrix *A, const ScsSettings *stgs,
|
|
216
|
+
const ScsScaling *scal) {
|
|
217
|
+
scs_int i, j;
|
|
218
|
+
scs_float *D = scal->D;
|
|
219
|
+
scs_float *E = scal->E;
|
|
220
|
+
for (i = 0; i < A->n; ++i) {
|
|
221
|
+
SCS(scale_array)
|
|
222
|
+
(&(A->x[A->p[i]]), E[i] / stgs->scale, A->p[i + 1] - A->p[i]);
|
|
223
|
+
}
|
|
224
|
+
for (i = 0; i < A->n; ++i) {
|
|
225
|
+
for (j = A->p[i]; j < A->p[i + 1]; ++j) {
|
|
226
|
+
A->x[j] *= D[A->i[j]];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
void SCS(_accum_by_atrans)(scs_int n, scs_float *Ax, scs_int *Ai, scs_int *Ap,
|
|
232
|
+
const scs_float *x, scs_float *y) {
|
|
233
|
+
/* y += A'*x
|
|
234
|
+
A in column compressed format
|
|
235
|
+
parallelizes over columns (rows of A')
|
|
236
|
+
*/
|
|
237
|
+
scs_int p, j;
|
|
238
|
+
scs_int c1, c2;
|
|
239
|
+
scs_float yj;
|
|
240
|
+
#if EXTRA_VERBOSE > 0
|
|
241
|
+
SCS(timer) mult_by_atrans_timer;
|
|
242
|
+
SCS(tic)(&mult_by_atrans_timer);
|
|
243
|
+
#endif
|
|
244
|
+
#ifdef _OPENMP
|
|
245
|
+
#pragma omp parallel for private(p, c1, c2, yj)
|
|
246
|
+
#endif
|
|
247
|
+
for (j = 0; j < n; j++) {
|
|
248
|
+
yj = y[j];
|
|
249
|
+
c1 = Ap[j];
|
|
250
|
+
c2 = Ap[j + 1];
|
|
251
|
+
for (p = c1; p < c2; p++) {
|
|
252
|
+
yj += Ax[p] * x[Ai[p]];
|
|
253
|
+
}
|
|
254
|
+
y[j] = yj;
|
|
255
|
+
}
|
|
256
|
+
#if EXTRA_VERBOSE > 0
|
|
257
|
+
scs_printf("mult By A trans time: %1.2es\n",
|
|
258
|
+
SCS(tocq)(&mult_by_atrans_timer) / 1e3);
|
|
259
|
+
#endif
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
scs_float SCS(cumsum)(scs_int *p, scs_int *c, scs_int n) {
|
|
263
|
+
scs_int i, nz = 0;
|
|
264
|
+
scs_float nz2 = 0;
|
|
265
|
+
if (!p || !c) {
|
|
266
|
+
return (-1);
|
|
267
|
+
} /* check inputs */
|
|
268
|
+
for (i = 0; i < n; i++) {
|
|
269
|
+
p[i] = nz;
|
|
270
|
+
nz += c[i];
|
|
271
|
+
nz2 += c[i]; /* also in scs_float to avoid scs_int overflow */
|
|
272
|
+
c[i] = p[i]; /* also copy p[0..n-1] back into c[0..n-1]*/
|
|
273
|
+
}
|
|
274
|
+
p[n] = nz;
|
|
275
|
+
return nz2; /* return sum (c [0..n-1]) */
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
void SCS(_accum_by_a)(scs_int n, scs_float *Ax, scs_int *Ai, scs_int *Ap,
|
|
279
|
+
const scs_float *x, scs_float *y) {
|
|
280
|
+
/*y += A*x
|
|
281
|
+
A in column compressed format
|
|
282
|
+
this parallelizes over columns and uses
|
|
283
|
+
pragma atomic to prevent concurrent writes to y
|
|
284
|
+
*/
|
|
285
|
+
scs_int p, j;
|
|
286
|
+
scs_int c1, c2;
|
|
287
|
+
scs_float xj;
|
|
288
|
+
#if EXTRA_VERBOSE > 0
|
|
289
|
+
SCS(timer) mult_by_a_timer;
|
|
290
|
+
SCS(tic)(&mult_by_a_timer);
|
|
291
|
+
#endif
|
|
292
|
+
/*#pragma omp parallel for private(p,c1,c2,xj) */
|
|
293
|
+
for (j = 0; j < n; j++) {
|
|
294
|
+
xj = x[j];
|
|
295
|
+
c1 = Ap[j];
|
|
296
|
+
c2 = Ap[j + 1];
|
|
297
|
+
for (p = c1; p < c2; p++) {
|
|
298
|
+
/*#pragma omp atomic */
|
|
299
|
+
y[Ai[p]] += Ax[p] * xj;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
#if EXTRA_VERBOSE > 0
|
|
303
|
+
scs_printf("mult By A time: %1.2es\n", SCS(tocq)(&mult_by_a_timer) / 1e3);
|
|
304
|
+
#endif
|
|
305
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#ifndef AMATRIX_H_GUARD
|
|
2
|
+
#define AMATRIX_H_GUARD
|
|
3
|
+
|
|
4
|
+
#ifdef __cplusplus
|
|
5
|
+
extern "C" {
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
#include "glbopts.h"
|
|
9
|
+
#include "linalg.h"
|
|
10
|
+
#include "linsys.h"
|
|
11
|
+
#include "scs.h"
|
|
12
|
+
#include "util.h"
|
|
13
|
+
|
|
14
|
+
/* this struct defines the data matrix A */
|
|
15
|
+
struct SCS_A_DATA_MATRIX {
|
|
16
|
+
/* A is supplied in column compressed format */
|
|
17
|
+
scs_float *x; /* A values, size: NNZ A */
|
|
18
|
+
scs_int *i; /* A row index, size: NNZ A */
|
|
19
|
+
scs_int *p; /* A column pointer, size: n+1 */
|
|
20
|
+
scs_int m, n; /* m rows, n cols */
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
void SCS(_accum_by_atrans)(scs_int n, scs_float *Ax, scs_int *Ai, scs_int *Ap,
|
|
24
|
+
const scs_float *x, scs_float *y);
|
|
25
|
+
void SCS(_accum_by_a)(scs_int n, scs_float *Ax, scs_int *Ai, scs_int *Ap,
|
|
26
|
+
const scs_float *x, scs_float *y);
|
|
27
|
+
void SCS(_normalize_a)(ScsMatrix *A, const ScsSettings *stgs, const ScsCone *k,
|
|
28
|
+
ScsScaling *scal);
|
|
29
|
+
void SCS(_un_normalize_a)(ScsMatrix *A, const ScsSettings *stgs,
|
|
30
|
+
const ScsScaling *scal);
|
|
31
|
+
scs_float SCS(cumsum)(scs_int *p, scs_int *c, scs_int n);
|
|
32
|
+
|
|
33
|
+
#ifdef __cplusplus
|
|
34
|
+
}
|
|
35
|
+
#endif
|
|
36
|
+
#endif
|
|
Binary file
|