scs 0.3.2 → 0.4.1

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +35 -6
  5. data/lib/scs/matrix.rb +72 -0
  6. data/lib/scs/solver.rb +19 -26
  7. data/lib/scs/version.rb +1 -1
  8. data/lib/scs.rb +1 -0
  9. data/vendor/scs/CITATION.cff +2 -2
  10. data/vendor/scs/CMakeLists.txt +285 -169
  11. data/vendor/scs/Makefile +43 -18
  12. data/vendor/scs/README.md +3 -1
  13. data/vendor/scs/include/cones.h +5 -3
  14. data/vendor/scs/include/glbopts.h +35 -17
  15. data/vendor/scs/include/linsys.h +8 -8
  16. data/vendor/scs/include/normalize.h +1 -0
  17. data/vendor/scs/include/rw.h +3 -3
  18. data/vendor/scs/include/scs.h +51 -24
  19. data/vendor/scs/include/scs_types.h +3 -1
  20. data/vendor/scs/include/scs_work.h +13 -15
  21. data/vendor/scs/include/util.h +4 -2
  22. data/vendor/scs/linsys/cpu/direct/private.c +32 -153
  23. data/vendor/scs/linsys/cpu/direct/private.h +6 -6
  24. data/vendor/scs/linsys/cpu/indirect/private.c +9 -22
  25. data/vendor/scs/linsys/cpu/indirect/private.h +4 -2
  26. data/vendor/scs/linsys/csparse.c +140 -12
  27. data/vendor/scs/linsys/csparse.h +10 -17
  28. data/vendor/scs/linsys/external/amd/LICENSE.txt +0 -897
  29. data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +4 -2
  30. data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +0 -5
  31. data/vendor/scs/linsys/gpu/gpu.c +4 -4
  32. data/vendor/scs/linsys/gpu/gpu.h +1 -1
  33. data/vendor/scs/linsys/gpu/indirect/private.c +15 -26
  34. data/vendor/scs/linsys/mkl/direct/private.c +182 -0
  35. data/vendor/scs/linsys/mkl/direct/private.h +38 -0
  36. data/vendor/scs/linsys/scs_matrix.c +49 -72
  37. data/vendor/scs/linsys/scs_matrix.h +4 -3
  38. data/vendor/scs/scs.mk +39 -30
  39. data/vendor/scs/src/aa.c +0 -4
  40. data/vendor/scs/src/cones.c +78 -184
  41. data/vendor/scs/src/exp_cone.c +399 -0
  42. data/vendor/scs/src/normalize.c +51 -0
  43. data/vendor/scs/src/rw.c +139 -76
  44. data/vendor/scs/src/scs.c +275 -202
  45. data/vendor/scs/src/util.c +36 -13
  46. data/vendor/scs/test/minunit.h +2 -1
  47. data/vendor/scs/test/problem_utils.h +5 -4
  48. data/vendor/scs/test/problems/degenerate.h +1 -0
  49. data/vendor/scs/test/problems/hs21_tiny_qp.h +2 -1
  50. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +13 -4
  51. data/vendor/scs/test/problems/infeasible_tiny_qp.h +1 -0
  52. data/vendor/scs/test/problems/max_ent +0 -0
  53. data/vendor/scs/test/problems/max_ent.h +8 -0
  54. data/vendor/scs/test/problems/qafiro_tiny_qp.h +2 -1
  55. data/vendor/scs/test/problems/random_prob.h +2 -39
  56. data/vendor/scs/test/problems/rob_gauss_cov_est.h +15 -3
  57. data/vendor/scs/test/problems/small_lp.h +4 -1
  58. data/vendor/scs/test/problems/small_qp.h +42 -7
  59. data/vendor/scs/test/problems/test_exp_cone.h +84 -0
  60. data/vendor/scs/test/problems/test_prob_from_data_file.h +57 -0
  61. data/vendor/scs/test/problems/test_validation.h +4 -1
  62. data/vendor/scs/test/problems/unbounded_tiny_qp.h +3 -3
  63. data/vendor/scs/test/random_socp_prob.c +3 -1
  64. data/vendor/scs/test/run_from_file.c +22 -4
  65. data/vendor/scs/test/run_tests.c +22 -9
  66. metadata +12 -4
@@ -50,7 +50,9 @@
50
50
 
51
51
  struct SuiteSparse_config_struct SuiteSparse_config =
52
52
  {
53
- scs_malloc, scs_calloc, scs_realloc, scs_free, _scs_printf,
53
+ scs_malloc, scs_calloc, scs_realloc, scs_free,
54
+ /* Disable printing */
55
+ SCS_NULL,
54
56
  SuiteSparse_hypot,
55
57
  SuiteSparse_divcomplex
56
58
 
@@ -79,7 +81,7 @@ void SuiteSparse_start ( void )
79
81
  SuiteSparse_config.calloc_func = scs_calloc ;
80
82
  SuiteSparse_config.realloc_func = scs_realloc ;
81
83
  SuiteSparse_config.free_func = scs_free ;
82
- SuiteSparse_config.printf_func = _scs_printf ;
84
+ SuiteSparse_config.printf_func = SCS_NULL;
83
85
  /* math functions */
84
86
  SuiteSparse_config.hypot_func = SuiteSparse_hypot ;
85
87
  SuiteSparse_config.divcomplex_func = SuiteSparse_divcomplex ;
@@ -71,11 +71,6 @@ extern "C" {
71
71
  #define SuiteSparse_long_id "%" SuiteSparse_long_idd
72
72
  #endif
73
73
 
74
- #ifndef _scs_printf
75
- #define _scs_printf scs_printf
76
- #endif
77
-
78
-
79
74
  /* ========================================================================== */
80
75
  /* === SuiteSparse_config parameters and functions ========================== */
81
76
  /* ========================================================================== */
@@ -19,13 +19,13 @@ void SCS(accum_by_atrans_gpu)(const ScsGpuMatrix *Ag,
19
19
  if (*buffer != SCS_NULL) {
20
20
  cudaFree(*buffer);
21
21
  }
22
- cudaMalloc(buffer, *buffer_size);
22
+ cudaMalloc(buffer, new_buffer_size);
23
23
  *buffer_size = new_buffer_size;
24
24
  }
25
25
 
26
26
  CUSPARSE_GEN(SpMV)
27
27
  (cusparse_handle, CUSPARSE_OPERATION_NON_TRANSPOSE, &onef, Ag->descr, x,
28
- &onef, y, SCS_CUDA_FLOAT, SCS_CSRMV_ALG, buffer);
28
+ &onef, y, SCS_CUDA_FLOAT, SCS_CSRMV_ALG, *buffer);
29
29
  }
30
30
 
31
31
  /* this is slow, use trans routine if possible */
@@ -48,13 +48,13 @@ void SCS(accum_by_a_gpu)(const ScsGpuMatrix *Ag, const cusparseDnVecDescr_t x,
48
48
  if (*buffer != SCS_NULL) {
49
49
  cudaFree(*buffer);
50
50
  }
51
- cudaMalloc(buffer, *buffer_size);
51
+ cudaMalloc(buffer, new_buffer_size);
52
52
  *buffer_size = new_buffer_size;
53
53
  }
54
54
 
55
55
  CUSPARSE_GEN(SpMV)
56
56
  (cusparse_handle, CUSPARSE_OPERATION_TRANSPOSE, &onef, Ag->descr, x, &onef, y,
57
- SCS_CUDA_FLOAT, SCS_CSRMV_ALG, buffer);
57
+ SCS_CUDA_FLOAT, SCS_CSRMV_ALG, *buffer);
58
58
  }
59
59
 
60
60
  /* This assumes that P has been made full (ie not triangular) and uses the
@@ -74,7 +74,7 @@ extern "C" {
74
74
  #define SCS_CUSPARSE_INDEX CUSPARSE_INDEX_64I
75
75
  #endif
76
76
 
77
- #define SCS_CSRMV_ALG CUSPARSE_CSRMV_ALG1
77
+ #define SCS_CSRMV_ALG CUSPARSE_SPMV_CSR_ALG1
78
78
  #define SCS_CSR2CSC_ALG CUSPARSE_CSR2CSC_ALG1
79
79
 
80
80
  /*
@@ -21,20 +21,10 @@ static scs_float cg_gpu_norm(cublasHandle_t cublas_handle, scs_float *r,
21
21
  return nrm;
22
22
  }
23
23
 
24
- const char *SCS(get_lin_sys_method)() {
24
+ const char *scs_get_lin_sys_method() {
25
25
  return "sparse-indirect GPU";
26
26
  }
27
27
 
28
- /*
29
- char *SCS(get_lin_sys_summary)(ScsLinSysWork *p, const ScsInfo *info) {
30
- char *str = (char *)scs_malloc(sizeof(char) * 128);
31
- sprintf(str, "lin-sys: avg cg its: %2.2f\n",
32
- (scs_float)p->tot_cg_its / (info->iter + 1));
33
- p->tot_cg_its = 0;
34
- return str;
35
- }
36
- */
37
-
38
28
  /* Not possible to do this on the fly due to M_ii += a_i' (R_y)^-1 a_i */
39
29
  /* set M = inv ( diag ( R_x + P + A' R_y^{-1} A ) ) */
40
30
  static void set_preconditioner(ScsLinSysWork *p, const scs_float *diag_r) {
@@ -76,7 +66,7 @@ static void set_preconditioner(ScsLinSysWork *p, const scs_float *diag_r) {
76
66
  }
77
67
 
78
68
  /* no need to update anything in this case */
79
- void SCS(update_lin_sys_diag_r)(ScsLinSysWork *p, const scs_float *diag_r) {
69
+ void scs_update_lin_sys_diag_r(ScsLinSysWork *p, const scs_float *diag_r) {
80
70
  scs_int i;
81
71
 
82
72
  /* R_x to gpu */
@@ -93,7 +83,7 @@ void SCS(update_lin_sys_diag_r)(ScsLinSysWork *p, const scs_float *diag_r) {
93
83
  set_preconditioner(p, diag_r);
94
84
  }
95
85
 
96
- void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
86
+ void scs_free_lin_sys_work(ScsLinSysWork *p) {
97
87
  if (p) {
98
88
  scs_free(p->M);
99
89
  scs_free(p->inv_r_y);
@@ -182,13 +172,13 @@ static void mat_vec(ScsLinSysWork *p, const scs_float *x, scs_float *y) {
182
172
  }
183
173
 
184
174
  /* P comes in upper triangular, expand to full
185
- * First compute triplet version of full matrix, then compress to csc
175
+ * First compute triplet version of full matrix, then compress to CSC
186
176
  * */
187
- static csc *fill_p_matrix(const ScsMatrix *P) {
177
+ static ScsMatrix *fill_p_matrix(const ScsMatrix *P) {
188
178
  scs_int i, j, k, kk;
189
179
  scs_int Pnzmax = 2 * P->p[P->n]; /* upper bound */
190
- csc *P_tmp = SCS(cs_spalloc)(P->n, P->n, Pnzmax, 1, 1);
191
- csc *P_full;
180
+ ScsMatrix *P_tmp = SCS(cs_spalloc)(P->n, P->n, Pnzmax, 1, 1);
181
+ ScsMatrix *P_full;
192
182
  kk = 0;
193
183
  for (j = 0; j < P->n; j++) { /* cols */
194
184
  for (k = P->p[j]; k < P->p[j + 1]; k++) {
@@ -209,16 +199,15 @@ static csc *fill_p_matrix(const ScsMatrix *P) {
209
199
  kk++;
210
200
  }
211
201
  }
212
- P_tmp->nz = kk; /* set number of nonzeros */
213
- P_full = SCS(cs_compress)(P_tmp, SCS_NULL);
202
+ P_full = SCS(cs_compress)(P_tmp, kk, SCS_NULL);
214
203
  SCS(cs_spfree)(P_tmp);
215
204
  return P_full;
216
205
  }
217
206
 
218
- ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
219
- const scs_float *diag_r) {
207
+ ScsLinSysWork *scs_init_lin_sys_work(const ScsMatrix *A, const ScsMatrix *P,
208
+ const scs_float *diag_r) {
220
209
  cudaError_t err;
221
- csc *P_full;
210
+ ScsMatrix *P_full;
222
211
  ScsLinSysWork *p = SCS_NULL;
223
212
  ScsGpuMatrix *Ag = SCS_NULL;
224
213
  ScsGpuMatrix *Pg = SCS_NULL;
@@ -324,7 +313,7 @@ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
324
313
  cusparseCreateDnVec(&p->dn_vec_m, Ag->m, p->tmp_m, SCS_CUDA_FLOAT);
325
314
 
326
315
  /* Form preconditioner and copy R_x, 1/R_y to gpu */
327
- SCS(update_lin_sys_diag_r)(p, diag_r);
316
+ scs_update_lin_sys_diag_r(p, diag_r);
328
317
 
329
318
  #if GPU_TRANSPOSE_MAT > 0
330
319
  p->Agt = (ScsGpuMatrix *)scs_malloc(sizeof(ScsGpuMatrix));
@@ -367,7 +356,7 @@ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
367
356
  if (err != cudaSuccess) {
368
357
  printf("%s:%d:%s\nERROR_CUDA (*): %s\n", __FILE__, __LINE__, __func__,
369
358
  cudaGetErrorString(err));
370
- SCS(free_lin_sys_work)(p);
359
+ scs_free_lin_sys_work(p);
371
360
  return SCS_NULL;
372
361
  }
373
362
  return p;
@@ -466,8 +455,8 @@ static scs_int pcg(ScsLinSysWork *pr, const scs_float *s, scs_float *bg,
466
455
  * y = R_y^{-1} (Ax - ry)
467
456
  *
468
457
  */
469
- scs_int SCS(solve_lin_sys)(ScsLinSysWork *p, scs_float *b, const scs_float *s,
470
- scs_float tol) {
458
+ scs_int scs_solve_lin_sys(ScsLinSysWork *p, scs_float *b, const scs_float *s,
459
+ scs_float tol) {
471
460
  scs_int cg_its, max_iters;
472
461
  scs_float neg_onef = -1.0;
473
462
 
@@ -0,0 +1,182 @@
1
+ #include "private.h"
2
+
3
+ #define PARDISO_SYMBOLIC (11)
4
+ #define PARDISO_NUMERIC (22)
5
+ #define PARDISO_SOLVE (33)
6
+ #define PARDISO_CLEANUP (-1)
7
+
8
+ /* TODO: is it necessary to use pardiso_64 and MKL_Set_Interface_Layer ? */
9
+ /*
10
+ #define MKL_INTERFACE_LP64 0
11
+ #define MKL_INTERFACE_ILP64 1
12
+ */
13
+ #ifdef DLONG
14
+ #define _PARDISO pardiso_64
15
+ #else
16
+ #define _PARDISO pardiso
17
+ #endif
18
+
19
+ /* Prototypes for Pardiso functions */
20
+ void _PARDISO(void **pt, const scs_int *maxfct, const scs_int *mnum,
21
+ const scs_int *mtype, const scs_int *phase, const scs_int *n,
22
+ const scs_float *a, const scs_int *ia, const scs_int *ja,
23
+ scs_int *perm, const scs_int *nrhs, scs_int *iparm,
24
+ const scs_int *msglvl, scs_float *b, scs_float *x,
25
+ scs_int *error);
26
+ /* scs_int MKL_Set_Interface_Layer(scs_int); */
27
+
28
+ const char *scs_get_lin_sys_method() {
29
+ return "sparse-direct-mkl-pardiso";
30
+ }
31
+
32
+ void scs_free_lin_sys_work(ScsLinSysWork *p) {
33
+ if (p) {
34
+ p->phase = PARDISO_CLEANUP;
35
+ _PARDISO(p->pt, &(p->maxfct), &(p->mnum), &(p->mtype), &(p->phase),
36
+ &(p->n_plus_m), SCS_NULL, p->kkt->p, p->kkt->i, SCS_NULL,
37
+ &(p->nrhs), p->iparm, &(p->msglvl), SCS_NULL, SCS_NULL,
38
+ &(p->error));
39
+ if (p->error != 0) {
40
+ scs_printf("Error during MKL Pardiso cleanup: %d", (int)p->error);
41
+ }
42
+ if (p->kkt)
43
+ SCS(cs_spfree)(p->kkt);
44
+ if (p->sol)
45
+ scs_free(p->sol);
46
+ if (p->diag_r_idxs)
47
+ scs_free(p->diag_r_idxs);
48
+ if (p->diag_p)
49
+ scs_free(p->diag_p);
50
+ scs_free(p);
51
+ }
52
+ }
53
+
54
+ ScsLinSysWork *scs_init_lin_sys_work(const ScsMatrix *A, const ScsMatrix *P,
55
+ const scs_float *diag_r) {
56
+ scs_int i;
57
+ ScsLinSysWork *p = scs_calloc(1, sizeof(ScsLinSysWork));
58
+
59
+ /* TODO: is this necessary with pardiso_64? */
60
+ /* Set MKL interface layer */
61
+ /*
62
+ #ifdef DLONG
63
+ MKL_Set_Interface_Layer(MKL_INTERFACE_ILP64);
64
+ #else
65
+ MKL_Set_Interface_Layer(MKL_INTERFACE_LP64);
66
+ #endif
67
+ */
68
+ p->n = A->n;
69
+ p->m = A->m;
70
+ p->n_plus_m = p->n + p->m;
71
+
72
+ /* Even though we overwrite rhs with sol pardiso requires the memory */
73
+ p->sol = (scs_float *)scs_malloc(sizeof(scs_float) * p->n_plus_m);
74
+ p->diag_r_idxs = (scs_int *)scs_calloc(p->n_plus_m, sizeof(scs_int));
75
+ p->diag_p = (scs_float *)scs_calloc(p->n, sizeof(scs_float));
76
+
77
+ /* MKL pardiso requires upper triangular CSR matrices. The KKT matrix stuffed
78
+ * as CSC lower triangular is equivalent. Pass upper=0. */
79
+ p->kkt = SCS(form_kkt)(A, P, p->diag_p, diag_r, p->diag_r_idxs, 0);
80
+ if (!(p->kkt)) {
81
+ scs_printf("Error in forming KKT matrix");
82
+ scs_free_lin_sys_work(p);
83
+ return SCS_NULL;
84
+ }
85
+
86
+ for (i = 0; i < 64; i++) {
87
+ p->iparm[i] = 0; /* Setup Pardiso control parameters */
88
+ p->pt[i] = 0; /* Initialize the internal solver memory pointer */
89
+ }
90
+
91
+ /* Set Pardiso variables */
92
+ p->mtype = -2; /* Real symmetric indefinite matrix */
93
+ p->nrhs = 1; /* Number of right hand sides */
94
+ p->maxfct = 1; /* Maximum number of numerical factorizations */
95
+ p->mnum = 1; /* Which factorization to use */
96
+ p->error = 0; /* Initialize error flag */
97
+ p->msglvl = VERBOSITY; /* Printing information */
98
+
99
+ /* For all iparm vars see MKL documentation */
100
+ p->iparm[0] = 1; /* Parsido must inspect iparm */
101
+ p->iparm[1] = 3; /* Fill-in reordering from OpenMP */
102
+ p->iparm[5] = 1; /* Write solution into b */
103
+ p->iparm[7] = 0; /* Automatic iterative refinement calculation */
104
+ p->iparm[9] = 8; /* Perturb the pivot elements with 1E-8 */
105
+ p->iparm[34] = 1; /* Use C-style indexing for indices */
106
+ /* p->iparm[36] = -80; */ /* Form block sparse matrices */
107
+
108
+ #ifdef SFLOAT
109
+ p->iparm[27] = 1; /* 1 is single precision, 0 is double */
110
+ #endif
111
+
112
+ /* Permutation and symbolic factorization */
113
+ scs_int phase = PARDISO_SYMBOLIC;
114
+ _PARDISO(p->pt, &(p->maxfct), &(p->mnum), &(p->mtype), &phase, &(p->n_plus_m),
115
+ p->kkt->x, p->kkt->p, p->kkt->i, SCS_NULL, &(p->nrhs), p->iparm,
116
+ &(p->msglvl), SCS_NULL, SCS_NULL, &(p->error));
117
+
118
+ if (p->error != 0) {
119
+ scs_printf("Error during symbolic factorization: %d", (int)p->error);
120
+ scs_free_lin_sys_work(p);
121
+ return SCS_NULL;
122
+ }
123
+
124
+ /* Numerical factorization */
125
+ p->phase = PARDISO_NUMERIC;
126
+ _PARDISO(p->pt, &(p->maxfct), &(p->mnum), &(p->mtype), &(p->phase),
127
+ &(p->n_plus_m), p->kkt->x, p->kkt->p, p->kkt->i, SCS_NULL,
128
+ &(p->nrhs), p->iparm, &(p->msglvl), SCS_NULL, SCS_NULL, &(p->error));
129
+
130
+ if (p->error) {
131
+ scs_printf("Error during numerical factorization: %d", (int)p->error);
132
+ scs_free_lin_sys_work(p);
133
+ return SCS_NULL;
134
+ }
135
+
136
+ if (p->iparm[21] < p->n) {
137
+ scs_printf("KKT matrix has < n positive eigenvalues. P not PSD.");
138
+ return SCS_NULL;
139
+ }
140
+
141
+ return p;
142
+ }
143
+
144
+ /* Returns solution to linear system Ax = b with solution stored in b */
145
+ scs_int scs_solve_lin_sys(ScsLinSysWork *p, scs_float *b, const scs_float *ws,
146
+ scs_float tol) {
147
+ /* Back substitution and iterative refinement */
148
+ p->phase = PARDISO_SOLVE;
149
+ _PARDISO(p->pt, &(p->maxfct), &(p->mnum), &(p->mtype), &(p->phase),
150
+ &(p->n_plus_m), p->kkt->x, p->kkt->p, p->kkt->i, SCS_NULL,
151
+ &(p->nrhs), p->iparm, &(p->msglvl), b, p->sol, &(p->error));
152
+ if (p->error != 0) {
153
+ scs_printf("Error during linear system solution: %d", (int)p->error);
154
+ }
155
+ return p->error;
156
+ }
157
+
158
+ /* Update factorization when R changes */
159
+ void scs_update_lin_sys_diag_r(ScsLinSysWork *p, const scs_float *diag_r) {
160
+ scs_int i;
161
+
162
+ for (i = 0; i < p->n; ++i) {
163
+ /* top left is R_x + P, bottom right is -R_y */
164
+ p->kkt->x[p->diag_r_idxs[i]] = p->diag_p[i] + diag_r[i];
165
+ }
166
+ for (i = p->n; i < p->n + p->m; ++i) {
167
+ /* top left is R_x + P, bottom right is -R_y */
168
+ p->kkt->x[p->diag_r_idxs[i]] = -diag_r[i];
169
+ }
170
+
171
+ /* Perform numerical factorization */
172
+ p->phase = PARDISO_NUMERIC;
173
+ _PARDISO(p->pt, &(p->maxfct), &(p->mnum), &(p->mtype), &(p->phase),
174
+ &(p->n_plus_m), p->kkt->x, p->kkt->p, p->kkt->i, SCS_NULL,
175
+ &(p->nrhs), p->iparm, &(p->msglvl), SCS_NULL, SCS_NULL, &(p->error));
176
+
177
+ if (p->error != 0) {
178
+ scs_printf("Error in PARDISO factorization when updating: %d.\n",
179
+ (int)p->error);
180
+ scs_free_lin_sys_work(p);
181
+ }
182
+ }
@@ -0,0 +1,38 @@
1
+ #ifndef PRIV_H_GUARD
2
+ #define PRIV_H_GUARD
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
8
+ #include "csparse.h"
9
+ #include "linsys.h"
10
+
11
+ struct SCS_LIN_SYS_WORK {
12
+ ScsMatrix *kkt; /* Upper triangular KKT matrix (in CSR format) */
13
+ scs_float *sol; /* solution to the KKT system */
14
+ scs_int n; /* number of QP variables */
15
+ scs_int m; /* number of QP constraints */
16
+
17
+ /* Pardiso variables */
18
+ void *pt[64]; /* internal solver memory pointer pt */
19
+ scs_int iparm[64]; /* Pardiso control parameters */
20
+ scs_int n_plus_m; /* dimension of the linear system */
21
+ scs_int mtype; /* matrix type (-2 for real and symmetric indefinite) */
22
+ scs_int nrhs; /* number of right-hand sides (1) */
23
+ scs_int maxfct; /* maximum number of factors (1) */
24
+ scs_int mnum; /* indicates matrix for the solution phase (1) */
25
+ scs_int phase; /* control the execution phases of the solver */
26
+ scs_int error; /* the error indicator (0 for no error) */
27
+ scs_int msglvl; /* Message level information (0 for no output) */
28
+
29
+ /* These are required for matrix updates */
30
+ scs_int *diag_r_idxs; /* indices where R appears */
31
+ scs_float *diag_p; /* Diagonal values of P */
32
+ };
33
+
34
+ #ifdef __cplusplus
35
+ }
36
+ #endif
37
+
38
+ #endif
@@ -10,6 +10,10 @@
10
10
  #define NUM_L2_PASSES (1) /* do one or zero, not more since not stable */
11
11
 
12
12
  scs_int SCS(copy_matrix)(ScsMatrix **dstp, const ScsMatrix *src) {
13
+ if (!src) {
14
+ *dstp = SCS_NULL;
15
+ return 1;
16
+ }
13
17
  scs_int Anz = src->p[src->n];
14
18
  ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
15
19
  if (!A) {
@@ -41,6 +45,8 @@ scs_int SCS(validate_lin_sys)(const ScsMatrix *A, const ScsMatrix *P) {
41
45
  }
42
46
  /* detects some errors in A col ptrs: */
43
47
  Anz = A->p[A->n];
48
+ /* Disable this check which is slowish and typically just produces noise. */
49
+ /*
44
50
  if (Anz > 0) {
45
51
  for (i = 0; i < A->n; ++i) {
46
52
  if (A->p[i] == A->p[i + 1]) {
@@ -53,6 +59,7 @@ scs_int SCS(validate_lin_sys)(const ScsMatrix *A, const ScsMatrix *P) {
53
59
  }
54
60
  }
55
61
  }
62
+ */
56
63
  if (((scs_float)Anz / A->m > A->n) || (Anz < 0)) {
57
64
  scs_printf("Anz (nonzeros in A) = %li, outside of valid range\n",
58
65
  (long)Anz);
@@ -106,18 +113,18 @@ static inline scs_float apply_limit(scs_float x) {
106
113
  return x;
107
114
  }
108
115
 
109
- static void compute_ruiz_mats(ScsMatrix *P, ScsMatrix *A, scs_float *b,
110
- scs_float *c, scs_float *Dt, scs_float *Et,
111
- scs_float *s, ScsConeWork *cone) {
116
+ static void compute_ruiz_mats(ScsMatrix *P, ScsMatrix *A, scs_float *Dt,
117
+ scs_float *Et, ScsConeWork *cone) {
112
118
  scs_int i, j, kk;
113
119
  scs_float wrk;
120
+ scs_float nm_a_col;
114
121
 
115
122
  /**************************** D ****************************/
116
123
 
117
124
  /* initialize D */
118
125
  for (i = 0; i < A->m; ++i) {
119
- /* Dt[i] = 0.; */
120
- Dt[i] = ABS(b[i]);
126
+ Dt[i] = 0.;
127
+ /* Dt[i] = ABS(b[i]); */
121
128
  }
122
129
 
123
130
  /* calculate row norms */
@@ -132,15 +139,16 @@ static void compute_ruiz_mats(ScsMatrix *P, ScsMatrix *A, scs_float *b,
132
139
 
133
140
  /* invert temporary vec to form D */
134
141
  for (i = 0; i < A->m; ++i) {
135
- Dt[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Dt[i])));
142
+ Dt[i] = SQRTF(apply_limit(Dt[i]));
143
+ Dt[i] = SAFEDIV_POS(1.0, Dt[i]);
136
144
  }
137
145
 
138
146
  /**************************** E ****************************/
139
147
 
140
148
  /* initialize E */
141
149
  for (i = 0; i < A->n; ++i) {
142
- /* Et[i] = 0.; */
143
- Et[i] = ABS(c[i]);
150
+ Et[i] = 0.;
151
+ /* Et[i] = ABS(c[i]); */
144
152
  }
145
153
 
146
154
  /* TODO: test not using P to determine scaling */
@@ -163,27 +171,24 @@ static void compute_ruiz_mats(ScsMatrix *P, ScsMatrix *A, scs_float *b,
163
171
 
164
172
  /* calculate col norms, E */
165
173
  for (i = 0; i < A->n; ++i) {
166
- Et[i] = MAX(Et[i], SCS(norm_inf)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]));
167
- Et[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Et[i])));
174
+ nm_a_col = SCS(norm_inf)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]);
175
+ Et[i] = MAX(Et[i], nm_a_col);
176
+ Et[i] = SQRTF(apply_limit(Et[i]));
177
+ Et[i] = SAFEDIV_POS(1.0, Et[i]);
168
178
  }
169
-
170
- /* calculate s value */
171
- *s = MAX(SCS(norm_inf)(c, A->n), SCS(norm_inf)(b, A->m));
172
- *s = SAFEDIV_POS(1.0, SQRTF(apply_limit(*s)));
173
179
  }
174
180
 
175
- static void compute_l2_mats(ScsMatrix *P, ScsMatrix *A, scs_float *b,
176
- scs_float *c, scs_float *Dt, scs_float *Et,
177
- scs_float *s, ScsConeWork *cone) {
181
+ static void compute_l2_mats(ScsMatrix *P, ScsMatrix *A, scs_float *Dt,
182
+ scs_float *Et, ScsConeWork *cone) {
178
183
  scs_int i, j, kk;
179
- scs_float wrk, norm_c, norm_b;
184
+ scs_float wrk;
180
185
 
181
186
  /**************************** D ****************************/
182
187
 
183
188
  /* initialize D */
184
189
  for (i = 0; i < A->m; ++i) {
185
- /* Dt[i] = 0.; */
186
- Dt[i] = b[i] * b[i];
190
+ Dt[i] = 0.;
191
+ /* Dt[i] = b[i] * b[i]; */
187
192
  }
188
193
 
189
194
  /* calculate row norms */
@@ -200,15 +205,16 @@ static void compute_l2_mats(ScsMatrix *P, ScsMatrix *A, scs_float *b,
200
205
  SCS(enforce_cone_boundaries)(cone, Dt, &SCS(mean));
201
206
 
202
207
  for (i = 0; i < A->m; ++i) {
203
- Dt[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Dt[i])));
208
+ Dt[i] = SQRTF(apply_limit(Dt[i]));
209
+ Dt[i] = SAFEDIV_POS(1.0, Dt[i]);
204
210
  }
205
211
 
206
212
  /**************************** E ****************************/
207
213
 
208
214
  /* initialize E */
209
215
  for (i = 0; i < A->n; ++i) {
210
- /* Et[i] = 0.; */
211
- Et[i] = c[i] * c[i];
216
+ Et[i] = 0.;
217
+ /* Et[i] = c[i] * c[i]; */
212
218
  }
213
219
 
214
220
  /* TODO: test not using P to determine scaling */
@@ -232,19 +238,13 @@ static void compute_l2_mats(ScsMatrix *P, ScsMatrix *A, scs_float *b,
232
238
  /* calculate col norms, E */
233
239
  for (i = 0; i < A->n; ++i) {
234
240
  Et[i] += SCS(norm_sq)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]);
235
- Et[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(SQRTF(Et[i]))));
241
+ Et[i] = SQRTF(apply_limit(SQRTF(Et[i])));
242
+ Et[i] = SAFEDIV_POS(1.0, Et[i]);
236
243
  }
237
-
238
- /* calculate s value */
239
- norm_c = SCS(norm_2)(c, A->n);
240
- norm_b = SCS(norm_2)(b, A->m);
241
- *s = SQRTF(norm_c * norm_c + norm_b * norm_b);
242
- *s = SAFEDIV_POS(1.0, SQRTF(apply_limit(*s)));
243
244
  }
244
245
 
245
- static void rescale(ScsMatrix *P, ScsMatrix *A, scs_float *b, scs_float *c,
246
- scs_float *Dt, scs_float *Et, scs_float s, ScsScaling *scal,
247
- ScsConeWork *cone) {
246
+ static void rescale(ScsMatrix *P, ScsMatrix *A, scs_float *Dt, scs_float *Et,
247
+ ScsScaling *scal, ScsConeWork *cone) {
248
248
  scs_int i, j;
249
249
  /* scale the rows of A with D */
250
250
  for (i = 0; i < A->n; ++i) {
@@ -271,15 +271,6 @@ static void rescale(ScsMatrix *P, ScsMatrix *A, scs_float *b, scs_float *c,
271
271
  }
272
272
  }
273
273
 
274
- /* scale c */
275
- for (i = 0; i < A->n; ++i) {
276
- c[i] *= Et[i];
277
- }
278
- /* scale b */
279
- for (i = 0; i < A->m; ++i) {
280
- b[i] *= Dt[i];
281
- }
282
-
283
274
  /* Accumulate scaling */
284
275
  for (i = 0; i < A->m; ++i) {
285
276
  scal->D[i] *= Dt[i];
@@ -288,53 +279,39 @@ static void rescale(ScsMatrix *P, ScsMatrix *A, scs_float *b, scs_float *c,
288
279
  scal->E[i] *= Et[i];
289
280
  }
290
281
 
291
- /* Apply scaling */
292
- SCS(scale_array)(c, s, A->n);
293
- SCS(scale_array)(b, s, A->m);
294
- /* no need to scale P since primal_scale = dual_scale */
282
+ /* no need to scale P since later primal_scale = dual_scale */
295
283
  /*
296
284
  if (P) {
297
285
  SCS(scale_array)(P->x, primal_scale, P->p[P->n]);
298
286
  SCS(scale_array)(P->x, 1.0 / dual_scale, P->p[P->n]);
299
287
  }
300
288
  */
301
-
302
- /* Accumulate scaling */
303
- scal->primal_scale *= s;
304
- scal->dual_scale *= s;
305
289
  }
306
290
 
307
- /* Will rescale as P -> EPE, A -> DAE, c -> sEc, b -> sDb, in-place.
291
+ /* Will rescale as P -> EPE, A -> DAE in-place.
308
292
  * Essentially trying to rescale this matrix:
309
293
  *
310
- * [P A' c] with [E 0 0] on both sides (D, E diagonal)
311
- * [A 0 b] [0 D 0]
312
- * [c' b' 0] [0 0 s]
294
+ * [P A'] with [E 0 ] on both sides (D, E diagonal)
295
+ * [A 0 ] [0 D ]
313
296
  *
314
297
  * which results in:
315
298
  *
316
- * [ EPE EA'D sEc ]
317
- * [ DAE 0 sDb ]
318
- * [ sc'E sb'D 0 ]
299
+ * [ EPE EA'D ]
300
+ * [ DAE 0 ]
319
301
  *
320
- * In other words D rescales the rows of A, b
321
- * E rescales the cols of A and rows/cols of P, c'
302
+ * In other words D rescales the rows of A
303
+ * E rescales the cols of A and rows/cols of P
322
304
  *
323
- * will repeatedly set: D^-1 ~ norm of rows of [ A b ]
305
+ * will repeatedly set: D^-1 ~ norm of rows of [ A ]
324
306
  *
325
307
  * E^-1 ~ norm of cols of [ P ]
326
308
  * [ A ]
327
- * [ c']
328
- *
329
- * `s` is incorporated into dual_scale and primal_scale
330
309
  *
331
310
  * The main complication is that D has to respect cone boundaries.
332
311
  *
333
312
  */
334
- ScsScaling *SCS(normalize_a_p)(ScsMatrix *P, ScsMatrix *A, scs_float *b,
335
- scs_float *c, ScsConeWork *cone) {
313
+ ScsScaling *SCS(normalize_a_p)(ScsMatrix *P, ScsMatrix *A, ScsConeWork *cone) {
336
314
  scs_int i;
337
- scs_float s;
338
315
  ScsScaling *scal = (ScsScaling *)scs_calloc(1, sizeof(ScsScaling));
339
316
  scs_float *Dt = (scs_float *)scs_calloc(A->m, sizeof(scs_float));
340
317
  scs_float *Et = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
@@ -359,12 +336,12 @@ ScsScaling *SCS(normalize_a_p)(ScsMatrix *P, ScsMatrix *A, scs_float *b,
359
336
  scal->primal_scale = 1.;
360
337
  scal->dual_scale = 1.;
361
338
  for (i = 0; i < NUM_RUIZ_PASSES; ++i) {
362
- compute_ruiz_mats(P, A, b, c, Dt, Et, &s, cone);
363
- rescale(P, A, b, c, Dt, Et, s, scal, cone);
339
+ compute_ruiz_mats(P, A, Dt, Et, cone);
340
+ rescale(P, A, Dt, Et, scal, cone);
364
341
  }
365
342
  for (i = 0; i < NUM_L2_PASSES; ++i) {
366
- compute_l2_mats(P, A, b, c, Dt, Et, &s, cone);
367
- rescale(P, A, b, c, Dt, Et, s, scal, cone);
343
+ compute_l2_mats(P, A, Dt, Et, cone);
344
+ rescale(P, A, Dt, Et, scal, cone);
368
345
  }
369
346
  scs_free(Dt);
370
347
  scs_free(Et);
@@ -378,14 +355,13 @@ ScsScaling *SCS(normalize_a_p)(ScsMatrix *P, ScsMatrix *A, scs_float *b,
378
355
  }
379
356
  scs_printf("primal_scale %g\n", scal->primal_scale);
380
357
  scs_printf("dual_scale %g\n", scal->dual_scale);
381
- scs_printf("norm_b %g\n", SCS(norm_inf)(b, A->m));
382
- scs_printf("norm_c %g\n", SCS(norm_inf)(c, A->n));
383
358
  scs_printf("norm D %g\n", SCS(norm_inf)(scal->D, A->m));
384
359
  scs_printf("norm E %g\n", SCS(norm_inf)(scal->E, A->n));
385
360
  #endif
386
361
  return scal;
387
362
  }
388
363
 
364
+ /*
389
365
  void SCS(un_normalize_a_p)(ScsMatrix *A, ScsMatrix *P, const ScsScaling *scal) {
390
366
  scs_int i, j;
391
367
  scs_float *D = scal->D;
@@ -411,6 +387,7 @@ void SCS(un_normalize_a_p)(ScsMatrix *A, ScsMatrix *P, const ScsScaling *scal) {
411
387
  }
412
388
  }
413
389
  }
390
+ */
414
391
 
415
392
  void SCS(accum_by_atrans)(const ScsMatrix *A, const scs_float *x,
416
393
  scs_float *y) {