scs 0.3.1 → 0.3.2

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +8 -8
  4. data/lib/scs/ffi.rb +1 -7
  5. data/lib/scs/version.rb +1 -1
  6. data/vendor/scs/CITATION.cff +1 -1
  7. data/vendor/scs/CMakeLists.txt +55 -7
  8. data/vendor/scs/Makefile +9 -9
  9. data/vendor/scs/README.md +2 -1
  10. data/vendor/scs/include/aa.h +1 -1
  11. data/vendor/scs/include/cones.h +14 -11
  12. data/vendor/scs/include/glbopts.h +26 -64
  13. data/vendor/scs/include/linalg.h +2 -1
  14. data/vendor/scs/include/linsys.h +13 -13
  15. data/vendor/scs/include/normalize.h +6 -5
  16. data/vendor/scs/include/scs.h +43 -87
  17. data/vendor/scs/include/scs_types.h +34 -0
  18. data/vendor/scs/include/scs_work.h +83 -0
  19. data/vendor/scs/linsys/cpu/direct/private.c +86 -73
  20. data/vendor/scs/linsys/cpu/direct/private.h +2 -2
  21. data/vendor/scs/linsys/cpu/indirect/private.c +42 -33
  22. data/vendor/scs/linsys/cpu/indirect/private.h +1 -2
  23. data/vendor/scs/linsys/csparse.c +3 -3
  24. data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +6 -6
  25. data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +6 -1
  26. data/vendor/scs/linsys/external/amd/amd_order.c +5 -5
  27. data/vendor/scs/linsys/gpu/gpu.h +8 -11
  28. data/vendor/scs/linsys/gpu/indirect/private.c +72 -49
  29. data/vendor/scs/linsys/gpu/indirect/private.h +14 -13
  30. data/vendor/scs/linsys/scs_matrix.c +26 -46
  31. data/vendor/scs/linsys/scs_matrix.h +4 -4
  32. data/vendor/scs/scs.mk +1 -1
  33. data/vendor/scs/src/aa.c +13 -4
  34. data/vendor/scs/src/cones.c +143 -92
  35. data/vendor/scs/src/linalg.c +25 -0
  36. data/vendor/scs/src/normalize.c +26 -26
  37. data/vendor/scs/src/rw.c +48 -12
  38. data/vendor/scs/src/scs.c +104 -110
  39. data/vendor/scs/src/scs_version.c +8 -6
  40. data/vendor/scs/src/util.c +1 -1
  41. data/vendor/scs/test/minunit.h +6 -1
  42. data/vendor/scs/test/problem_utils.h +28 -35
  43. data/vendor/scs/test/problems/degenerate.h +1 -1
  44. data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -1
  45. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +1 -1
  46. data/vendor/scs/test/problems/infeasible_tiny_qp.h +1 -1
  47. data/vendor/scs/test/problems/qafiro_tiny_qp.h +3 -3
  48. data/vendor/scs/test/problems/random_prob.h +1 -1
  49. data/vendor/scs/test/problems/rob_gauss_cov_est.h +1 -1
  50. data/vendor/scs/test/problems/small_lp.h +3 -1
  51. data/vendor/scs/test/problems/small_qp.h +352 -0
  52. data/vendor/scs/test/problems/{test_fails.h → test_validation.h} +3 -3
  53. data/vendor/scs/test/problems/unbounded_tiny_qp.h +1 -1
  54. data/vendor/scs/test/random_socp_prob.c +1 -1
  55. data/vendor/scs/test/run_from_file.c +1 -1
  56. data/vendor/scs/test/run_tests.c +23 -14
  57. metadata +8 -5
@@ -10,18 +10,15 @@
10
10
  #define BOX_CONE_MAX_ITERS (25)
11
11
  #define POW_CONE_MAX_ITERS (20)
12
12
 
13
- /* In the box cone projection we penalize the `t` term additionally by this
14
- * factor. This encourages the `t` term to stay close to the incoming `t` term,
15
- * which should provide better convergence since typically the `t` term does
16
- * not appear in the linear system other than `t = 1`. Setting to 1 is
17
- * the vanilla projection.
18
- */
19
- #define BOX_T_SCALE (1.)
20
-
21
13
  /* Box cone limits (+ or -) taken to be INF */
22
14
  #define MAX_BOX_VAL (1e15)
23
15
 
24
16
  #ifdef USE_LAPACK
17
+
18
+ #ifdef __cplusplus
19
+ extern "C" {
20
+ #endif
21
+
25
22
  void BLAS(syev)(const char *jobz, const char *uplo, blas_int *n, scs_float *a,
26
23
  blas_int *lda, scs_float *w, scs_float *work, blas_int *lwork,
27
24
  blas_int *info);
@@ -31,34 +28,43 @@ blas_int BLAS(syrk)(const char *uplo, const char *trans, const blas_int *n,
31
28
  const scs_float *beta, scs_float *c, const blas_int *ldc);
32
29
  void BLAS(scal)(const blas_int *n, const scs_float *sa, scs_float *sx,
33
30
  const blas_int *incx);
31
+
32
+ #ifdef __cplusplus
33
+ }
34
+ #endif
35
+
34
36
  #endif
35
37
 
36
38
  /* set the vector of rho y terms, based on scale and cones */
37
- void SCS(set_rho_y_vec)(const ScsCone *k, scs_float scale, scs_float *rho_y_vec,
38
- scs_int m) {
39
- scs_int i, count = 0;
40
- /* f cone */
41
- for (i = 0; i < k->z; ++i) {
39
+ void SCS(set_r_y)(const ScsConeWork *c, scs_float scale, scs_float *r_y) {
40
+ scs_int i;
41
+ /* z cone */
42
+ for (i = 0; i < c->k->z; ++i) {
42
43
  /* set rho_y small for z, similar to rho_x term, since z corresponds to
43
44
  * dual free cone, this effectively decreases penalty on those entries
44
45
  * and lets them be determined almost entirely by the linear system solve
45
46
  */
46
- rho_y_vec[i] = 1.0 / (1000. * scale);
47
+ r_y[i] = 1.0 / (1000. * scale);
47
48
  }
48
- count += k->z;
49
49
  /* others */
50
- for (i = count; i < m; ++i) {
51
- rho_y_vec[i] = 1.0 / scale;
50
+ for (i = c->k->z; i < c->m; ++i) {
51
+ r_y[i] = 1.0 / scale;
52
52
  }
53
+ }
53
54
 
54
- /* Note, if updating this to use different scales for other cones (e.g. box)
55
- * then you must be careful to also include the effect of the rho_y_vec
56
- * in the cone projection operator.
57
- */
58
-
59
- /* Increase rho_y_vec for the t term in the box cone */
60
- if (k->bsize) {
61
- rho_y_vec[k->z + k->l] *= BOX_T_SCALE;
55
+ /* the function f aggregates the entries within each cone */
56
+ void SCS(enforce_cone_boundaries)(const ScsConeWork *c, scs_float *vec,
57
+ scs_float (*f)(const scs_float *, scs_int)) {
58
+ scs_int i, j, delta;
59
+ scs_int count = c->cone_boundaries[0];
60
+ scs_float wrk;
61
+ for (i = 1; i < c->cone_boundaries_len; ++i) {
62
+ delta = c->cone_boundaries[i];
63
+ wrk = f(&(vec[count]), delta);
64
+ for (j = count; j < count + delta; ++j) {
65
+ vec[j] = wrk;
66
+ }
67
+ count += delta;
62
68
  }
63
69
  }
64
70
 
@@ -71,7 +77,7 @@ static inline scs_int get_sd_cone_size(scs_int s) {
71
77
  * cone boundaries, boundaries[0] is starting index for cones of size strictly
72
78
  * larger than 1, boundaries malloc-ed here so should be freed.
73
79
  */
74
- scs_int SCS(set_cone_boundaries)(const ScsCone *k, scs_int **cone_boundaries) {
80
+ void set_cone_boundaries(const ScsCone *k, ScsConeWork *c) {
75
81
  scs_int i, s_cone_sz, count = 0;
76
82
  scs_int cone_boundaries_len =
77
83
  1 + k->qsize + k->ssize + k->ed + k->ep + k->psize;
@@ -99,8 +105,8 @@ scs_int SCS(set_cone_boundaries)(const ScsCone *k, scs_int **cone_boundaries) {
99
105
  }
100
106
  count += k->psize;
101
107
  /* other cones */
102
- *cone_boundaries = b;
103
- return cone_boundaries_len;
108
+ c->cone_boundaries = b;
109
+ c->cone_boundaries_len = cone_boundaries_len;
104
110
  }
105
111
 
106
112
  static scs_int get_full_cone_dims(const ScsCone *k) {
@@ -121,7 +127,7 @@ static scs_int get_full_cone_dims(const ScsCone *k) {
121
127
  if (k->ep) {
122
128
  c += 3 * k->ep;
123
129
  }
124
- if (k->p) {
130
+ if (k->psize) {
125
131
  c += 3 * k->psize;
126
132
  }
127
133
  return c;
@@ -216,6 +222,9 @@ void SCS(finish_cone)(ScsConeWork *c) {
216
222
  scs_free(c->work);
217
223
  }
218
224
  #endif
225
+ if (c->cone_boundaries) {
226
+ scs_free(c->cone_boundaries);
227
+ }
219
228
  if (c->s) {
220
229
  scs_free(c->s);
221
230
  }
@@ -484,7 +493,7 @@ static scs_int proj_semi_definite_cone(scs_float *X, const scs_int n,
484
493
  /* Solve eigenproblem, reuse workspaces */
485
494
  BLAS(syev)("Vectors", "Lower", &nb, Xs, &nb, e, work, &lwork, &info);
486
495
  if (info != 0) {
487
- scs_printf("WARN: LAPACK syev error, info = %i\n", info);
496
+ scs_printf("WARN: LAPACK syev error, info = %i\n", (int)info);
488
497
  if (info < 0) {
489
498
  return info;
490
499
  }
@@ -587,36 +596,40 @@ static void normalize_box_cone(ScsConeWork *c, scs_float *D, scs_int bsize) {
587
596
  }
588
597
  }
589
598
 
590
- /* project onto { (t, s) | t * l <= s <= t * u, t >= 0 }, Newton's method on t
591
- tx = [t; s], total length = bsize
592
- uses Moreau since \Pi_K*(tx) = \Pi_K(-tx) + tx
599
+ /* Project onto { (t, s) | t * l <= s <= t * u, t >= 0 }, Newton's method on t
600
+ tx = [t; s], total length = bsize, under Euclidean metric 1/r_box.
593
601
  */
594
602
  static scs_float proj_box_cone(scs_float *tx, const scs_float *bl,
595
603
  const scs_float *bu, scs_int bsize,
596
- scs_float t_warm_start) {
604
+ scs_float t_warm_start, scs_float *r_box) {
597
605
  scs_float *x, gt, ht, t_prev, t = t_warm_start;
606
+ scs_float rho_t = 1, *rho = SCS_NULL, r;
598
607
  scs_int iter, j;
599
608
 
600
609
  if (bsize == 1) { /* special case */
601
610
  tx[0] = MAX(tx[0], 0.0);
602
611
  return tx[0];
603
612
  }
604
-
605
613
  x = &(tx[1]);
606
614
 
615
+ if (r_box) {
616
+ rho_t = 1.0 / r_box[0];
617
+ rho = &(r_box[1]);
618
+ }
619
+
607
620
  /* should only require about 5 or so iterations, 1 or 2 if warm-started */
608
621
  for (iter = 0; iter < BOX_CONE_MAX_ITERS; iter++) {
609
622
  t_prev = t;
610
- /* incorporate the additional BOX_T_SCALE factor into the projection */
611
- gt = BOX_T_SCALE * (t - tx[0]); /* gradient */
612
- ht = BOX_T_SCALE; /* hessian */
623
+ gt = rho_t * (t - tx[0]); /* gradient */
624
+ ht = rho_t; /* hessian */
613
625
  for (j = 0; j < bsize - 1; j++) {
626
+ r = rho ? 1.0 / rho[j] : 1.;
614
627
  if (x[j] > t * bu[j]) {
615
- gt += (t * bu[j] - x[j]) * bu[j]; /* gradient */
616
- ht += bu[j] * bu[j]; /* hessian */
628
+ gt += r * (t * bu[j] - x[j]) * bu[j]; /* gradient */
629
+ ht += r * bu[j] * bu[j]; /* hessian */
617
630
  } else if (x[j] < t * bl[j]) {
618
- gt += (t * bl[j] - x[j]) * bl[j]; /* gradient */
619
- ht += bl[j] * bl[j]; /* hessian */
631
+ gt += r * (t * bl[j] - x[j]) * bl[j]; /* gradient */
632
+ ht += r * bl[j] * bl[j]; /* hessian */
620
633
  }
621
634
  }
622
635
  t = MAX(t - gt / MAX(ht, 1e-8), 0.); /* newton step */
@@ -647,6 +660,7 @@ static scs_float proj_box_cone(scs_float *tx, const scs_float *bl,
647
660
  /* x[j] unchanged otherwise */
648
661
  }
649
662
  tx[0] = t;
663
+
650
664
  #if VERBOSITY > 3
651
665
  scs_printf("box cone iters %i\n", (int)iter + 1);
652
666
  #endif
@@ -718,18 +732,23 @@ static void proj_power_cone(scs_float *v, scs_float a) {
718
732
  }
719
733
 
720
734
  /* project onto the primal K cone in the paper */
735
+ /* the r_y vector determines the INVERSE metric, ie, project under the
736
+ * diag(r_y)^-1 norm.
737
+ */
721
738
  static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
722
- scs_int normalize) {
739
+ scs_int normalize, scs_float *r_y) {
723
740
  scs_int i, status;
724
741
  scs_int count = 0;
742
+ scs_float *r_box = SCS_NULL;
743
+ scs_float *bu, *bl;
725
744
 
726
- if (k->z) {
745
+ if (k->z) { /* doesn't use r_y */
727
746
  /* project onto primal zero / dual free cone */
728
747
  memset(x, 0, k->z * sizeof(scs_float));
729
748
  count += k->z;
730
749
  }
731
750
 
732
- if (k->l) {
751
+ if (k->l) { /* doesn't use r_y */
733
752
  /* project onto positive orthant */
734
753
  for (i = count; i < count + k->l; ++i) {
735
754
  x[i] = MAX(x[i], 0.0);
@@ -737,19 +756,19 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
737
756
  count += k->l;
738
757
  }
739
758
 
740
- if (k->bsize) {
741
- /* project onto box cone */
742
- if (normalize) {
743
- c->box_t_warm_start = proj_box_cone(&(x[count]), c->bl, c->bu, k->bsize,
744
- c->box_t_warm_start);
745
- } else {
746
- c->box_t_warm_start = proj_box_cone(&(x[count]), k->bl, k->bu, k->bsize,
747
- c->box_t_warm_start);
759
+ if (k->bsize) { /* DOES use r_y */
760
+ if (r_y) {
761
+ r_box = &(r_y[count]);
748
762
  }
763
+ /* project onto box cone */
764
+ bu = normalize ? c->bu : k->bu;
765
+ bl = normalize ? c->bl : k->bl;
766
+ c->box_t_warm_start = proj_box_cone(&(x[count]), bl, bu, k->bsize,
767
+ c->box_t_warm_start, r_box);
749
768
  count += k->bsize; /* since b = (t,s), len(s) = bsize - 1 */
750
769
  }
751
770
 
752
- if (k->qsize && k->q) {
771
+ if (k->qsize && k->q) { /* doesn't use r_y */
753
772
  /* project onto second-order cones */
754
773
  for (i = 0; i < k->qsize; ++i) {
755
774
  proj_soc(&(x[count]), k->q[i]);
@@ -757,7 +776,7 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
757
776
  }
758
777
  }
759
778
 
760
- if (k->ssize && k->s) {
779
+ if (k->ssize && k->s) { /* doesn't use r_y */
761
780
  /* project onto PSD cones */
762
781
  for (i = 0; i < k->ssize; ++i) {
763
782
  status = proj_semi_definite_cone(&(x[count]), k->s[i], c);
@@ -768,13 +787,13 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
768
787
  }
769
788
  }
770
789
 
771
- if (k->ep) {
772
- /*
773
- * exponential cone is not self dual, if s \in K
774
- * then y \in K^* and so if K is the primal cone
775
- * here we project onto K^*, via Moreau
776
- * \Pi_C^*(y) = y + \Pi_C(-y)
777
- */
790
+ if (k->ep) { /* doesn't use r_y */
791
+ /*
792
+ * exponential cone is not self dual, if s \in K
793
+ * then y \in K^* and so if K is the primal cone
794
+ * here we project onto K^*, via Moreau
795
+ * \Pi_C^*(y) = y + \Pi_C(-y)
796
+ */
778
797
  #ifdef _OPENMP
779
798
  #pragma omp parallel for
780
799
  #endif
@@ -784,7 +803,8 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
784
803
  count += 3 * k->ep;
785
804
  }
786
805
 
787
- if (k->ed) { /* dual exponential cone */
806
+ /* dual exponential cone */
807
+ if (k->ed) { /* doesn't use r_y */
788
808
  /*
789
809
  * exponential cone is not self dual, if s \in K
790
810
  * then y \in K^* and so if K is the primal cone
@@ -812,7 +832,7 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
812
832
  count += 3 * k->ed;
813
833
  }
814
834
 
815
- if (k->psize && k->p) {
835
+ if (k->psize && k->p) { /* doesn't use r_y */
816
836
  scs_float v[3];
817
837
  scs_int idx;
818
838
  /* don't use openmp for power cone
@@ -820,7 +840,7 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
820
840
  pragma omp parallel for private(v, idx)
821
841
  endif
822
842
  */
823
- for (i = 0; i < k->psize; ++i) {
843
+ for (i = 0; i < k->psize; ++i) { /* doesn't use r_y */
824
844
  idx = count + 3 * i;
825
845
  if (k->p[i] >= 0) {
826
846
  /* primal power cone */
@@ -844,11 +864,23 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
844
864
  return 0;
845
865
  }
846
866
 
847
- ScsConeWork *SCS(init_cone)(const ScsCone *k, const ScsScaling *scal,
848
- scs_int cone_len) {
867
+ ScsConeWork *SCS(init_cone)(const ScsCone *k, scs_int m) {
849
868
  ScsConeWork *c = (ScsConeWork *)scs_calloc(1, sizeof(ScsConeWork));
850
- c->cone_len = cone_len;
851
- c->s = (scs_float *)scs_calloc(cone_len, sizeof(scs_float));
869
+ c->k = k;
870
+ c->m = m;
871
+ c->scaled_cones = 0;
872
+ set_cone_boundaries(k, c);
873
+ c->s = (scs_float *)scs_calloc(m, sizeof(scs_float));
874
+ if (k->ssize && k->s) {
875
+ if (set_up_sd_cone_work_space(c, k) < 0) {
876
+ SCS(finish_cone)(c);
877
+ return SCS_NULL;
878
+ }
879
+ }
880
+ return c;
881
+ }
882
+
883
+ void scale_box_cone(const ScsCone *k, ScsConeWork *c, ScsScaling *scal) {
852
884
  if (k->bsize && k->bu && k->bl) {
853
885
  c->box_t_warm_start = 1.;
854
886
  if (scal) {
@@ -857,33 +889,52 @@ ScsConeWork *SCS(init_cone)(const ScsCone *k, const ScsScaling *scal,
857
889
  memcpy(c->bu, k->bu, (k->bsize - 1) * sizeof(scs_float));
858
890
  memcpy(c->bl, k->bl, (k->bsize - 1) * sizeof(scs_float));
859
891
  /* also does some sanitizing */
860
- normalize_box_cone(c, scal ? &(scal->D[k->z + k->l]) : SCS_NULL,
861
- k->bsize);
862
- }
863
- }
864
- if (k->ssize && k->s) {
865
- if (set_up_sd_cone_work_space(c, k) < 0) {
866
- SCS(finish_cone)(c);
867
- return SCS_NULL;
892
+ normalize_box_cone(c, &(scal->D[k->z + k->l]), k->bsize);
868
893
  }
869
894
  }
870
- return c;
871
895
  }
872
896
 
873
- /* outward facing cone projection routine
874
- performs projection in-place
875
- if normalize > 0 then will use normalized (equilibrated) cones if applicable.
897
+ /* Outward facing cone projection routine, performs projection in-place.
898
+ If normalize > 0 then will use normalized (equilibrated) cones if applicable.
899
+
900
+ Moreau decomposition for R-norm projections:
901
+
902
+ `x + R^{-1} \Pi_{C^*}^{R^{-1}} ( - R x ) = \Pi_C^R ( x )`
903
+
904
+ where \Pi^R_C is the projection onto C under the R-norm:
905
+
906
+ `||x||_R = \sqrt{x ' R x}`.
907
+
876
908
  */
877
- scs_int SCS(proj_dual_cone)(scs_float *x, const ScsCone *k, ScsConeWork *c,
878
- scs_int normalize) {
879
- scs_int status;
880
- /* copy x, s = x */
881
- memcpy(c->s, x, c->cone_len * sizeof(scs_float));
882
- /* negate x -> -x */
883
- SCS(scale_array)(x, -1., c->cone_len);
884
- /* project -x onto cone, x -> Pi_K(-x) */
885
- status = proj_cone(x, k, c, normalize);
886
- /* return Pi_K*(x) = s + Pi_K(-x) */
887
- SCS(add_scaled_array)(x, c->s, c->cone_len, 1.);
909
+ scs_int SCS(proj_dual_cone)(scs_float *x, ScsConeWork *c, ScsScaling *scal,
910
+ scs_float *r_y) {
911
+ scs_int status, i;
912
+ const ScsCone *k = c->k;
913
+
914
+ if (!c->scaled_cones) {
915
+ scale_box_cone(k, c, scal);
916
+ c->scaled_cones = 1;
917
+ }
918
+
919
+ /* copy s = x */
920
+ memcpy(c->s, x, c->m * sizeof(scs_float));
921
+
922
+ /* x -> - Rx */
923
+ for (i = 0; i < c->m; ++i) {
924
+ x[i] *= r_y ? -r_y[i] : -1;
925
+ }
926
+
927
+ /* project -x onto cone, x -> \Pi_{C^*}^{R^{-1}}(-x) under r_y metric */
928
+ status = proj_cone(x, k, c, scal ? 1 : 0, r_y);
929
+
930
+ /* return x + R^{-1} \Pi_{C^*}^{R^{-1}} ( -x ) */
931
+ for (i = 0; i < c->m; ++i) {
932
+ if (r_y) {
933
+ x[i] = x[i] / r_y[i] + c->s[i];
934
+ } else {
935
+ x[i] += c->s[i];
936
+ }
937
+ }
938
+
888
939
  return status;
889
940
  }
@@ -83,9 +83,22 @@ void SCS(add_scaled_array)(scs_float *a, const scs_float *b, scs_int n,
83
83
  }
84
84
  }
85
85
 
86
+ scs_float SCS(mean)(const scs_float *x, scs_int n) {
87
+ scs_int i;
88
+ scs_float mean = 0.;
89
+ for (i = 0; i < n; ++i) {
90
+ mean += x[i];
91
+ }
92
+ return mean / n;
93
+ }
94
+
86
95
  #else
87
96
  /* If we have BLAS / LAPACK we may as well use them */
88
97
 
98
+ #ifdef __cplusplus
99
+ extern "C" {
100
+ #endif
101
+
89
102
  scs_float BLAS(nrm2)(blas_int *n, const scs_float *x, blas_int *incx);
90
103
  scs_float BLAS(dot)(const blas_int *n, const scs_float *x, const blas_int *incx,
91
104
  const scs_float *y, const blas_int *incy);
@@ -96,6 +109,10 @@ void BLAS(axpy)(blas_int *n, const scs_float *a, const scs_float *x,
96
109
  void BLAS(scal)(const blas_int *n, const scs_float *sa, scs_float *sx,
97
110
  const blas_int *incx);
98
111
 
112
+ #ifdef __cplusplus
113
+ }
114
+ #endif
115
+
99
116
  /* a *= b */
100
117
  void SCS(scale_array)(scs_float *a, const scs_float b, scs_int len) {
101
118
  blas_int bone = 1;
@@ -137,4 +154,12 @@ void SCS(add_scaled_array)(scs_float *a, const scs_float *b, scs_int len,
137
154
  BLAS(axpy)(&blen, &sc, b, &bone, a, &bone);
138
155
  }
139
156
 
157
+ scs_float SCS(mean)(const scs_float *x, scs_int n) {
158
+ blas_int bone = 1;
159
+ blas_int bzero = 0;
160
+ blas_int blen = (blas_int)n;
161
+ scs_float y = 1.0;
162
+ return BLAS(dot)(&blen, x, &bone, &y, &bzero) / n;
163
+ }
164
+
140
165
  #endif
@@ -4,48 +4,48 @@
4
4
  #include "scs.h"
5
5
 
6
6
  /* needed for normalizing the warm-start */
7
- void SCS(normalize_sol)(ScsWork *w, ScsSolution *sol) {
7
+ void SCS(normalize_sol)(ScsScaling *scal, ScsSolution *sol) {
8
8
  scs_int i;
9
- scs_float *D = w->scal->D;
10
- scs_float *E = w->scal->E;
11
- for (i = 0; i < w->n; ++i) {
12
- sol->x[i] /= (E[i] / w->scal->dual_scale);
9
+ scs_float *D = scal->D;
10
+ scs_float *E = scal->E;
11
+ for (i = 0; i < scal->n; ++i) {
12
+ sol->x[i] /= (E[i] / scal->dual_scale);
13
13
  }
14
- for (i = 0; i < w->m; ++i) {
15
- sol->y[i] /= (D[i] / w->scal->primal_scale);
14
+ for (i = 0; i < scal->m; ++i) {
15
+ sol->y[i] /= (D[i] / scal->primal_scale);
16
16
  }
17
- for (i = 0; i < w->m; ++i) {
18
- sol->s[i] *= (D[i] * w->scal->dual_scale);
17
+ for (i = 0; i < scal->m; ++i) {
18
+ sol->s[i] *= (D[i] * scal->dual_scale);
19
19
  }
20
20
  }
21
21
 
22
- void SCS(un_normalize_sol)(ScsWork *w, ScsSolution *sol) {
22
+ void SCS(un_normalize_sol)(ScsScaling *scal, ScsSolution *sol) {
23
23
  scs_int i;
24
- scs_float *D = w->scal->D;
25
- scs_float *E = w->scal->E;
26
- for (i = 0; i < w->n; ++i) {
27
- sol->x[i] *= (E[i] / w->scal->dual_scale);
24
+ scs_float *D = scal->D;
25
+ scs_float *E = scal->E;
26
+ for (i = 0; i < scal->n; ++i) {
27
+ sol->x[i] *= (E[i] / scal->dual_scale);
28
28
  }
29
- for (i = 0; i < w->m; ++i) {
30
- sol->y[i] *= (D[i] / w->scal->primal_scale);
29
+ for (i = 0; i < scal->m; ++i) {
30
+ sol->y[i] *= (D[i] / scal->primal_scale);
31
31
  }
32
- for (i = 0; i < w->m; ++i) {
33
- sol->s[i] /= (D[i] * w->scal->dual_scale);
32
+ for (i = 0; i < scal->m; ++i) {
33
+ sol->s[i] /= (D[i] * scal->dual_scale);
34
34
  }
35
35
  }
36
36
 
37
- void SCS(un_normalize_primal)(ScsWork *w, scs_float *r) {
37
+ void SCS(un_normalize_primal)(ScsScaling *scal, scs_float *r) {
38
38
  scs_int i;
39
- scs_float *D = w->scal->D;
40
- for (i = 0; i < w->m; ++i) {
41
- r[i] /= (D[i] * w->scal->dual_scale);
39
+ scs_float *D = scal->D;
40
+ for (i = 0; i < scal->m; ++i) {
41
+ r[i] /= (D[i] * scal->dual_scale);
42
42
  }
43
43
  }
44
44
 
45
- void SCS(un_normalize_dual)(ScsWork *w, scs_float *r) {
45
+ void SCS(un_normalize_dual)(ScsScaling *scal, scs_float *r) {
46
46
  scs_int i;
47
- scs_float *E = w->scal->E;
48
- for (i = 0; i < w->n; ++i) {
49
- r[i] /= (E[i] * w->scal->primal_scale);
47
+ scs_float *E = scal->E;
48
+ for (i = 0; i < scal->n; ++i) {
49
+ r[i] /= (E[i] * scal->primal_scale);
50
50
  }
51
51
  }
data/vendor/scs/src/rw.c CHANGED
@@ -33,20 +33,20 @@ static ScsCone *read_scs_cone(FILE *fin) {
33
33
  fread(&(k->z), sizeof(scs_int), 1, fin);
34
34
  fread(&(k->l), sizeof(scs_int), 1, fin);
35
35
  fread(&(k->bsize), sizeof(scs_int), 1, fin);
36
- k->bl = scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
37
- k->bu = scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
36
+ k->bl = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
37
+ k->bu = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
38
38
  fread(k->bl, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
39
39
  fread(k->bu, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
40
40
  fread(&(k->qsize), sizeof(scs_int), 1, fin);
41
- k->q = scs_calloc(k->qsize, sizeof(scs_int));
41
+ k->q = (scs_int *)scs_calloc(k->qsize, sizeof(scs_int));
42
42
  fread(k->q, sizeof(scs_int), k->qsize, fin);
43
43
  fread(&(k->ssize), sizeof(scs_int), 1, fin);
44
- k->s = scs_calloc(k->ssize, sizeof(scs_int));
44
+ k->s = (scs_int *)scs_calloc(k->ssize, sizeof(scs_int));
45
45
  fread(k->s, sizeof(scs_int), k->ssize, fin);
46
46
  fread(&(k->ep), sizeof(scs_int), 1, fin);
47
47
  fread(&(k->ed), sizeof(scs_int), 1, fin);
48
48
  fread(&(k->psize), sizeof(scs_int), 1, fin);
49
- k->p = scs_calloc(k->psize, sizeof(scs_float));
49
+ k->p = (scs_float *)scs_calloc(k->psize, sizeof(scs_float));
50
50
  fread(k->p, sizeof(scs_float), k->psize, fin);
51
51
  return k;
52
52
  }
@@ -103,11 +103,11 @@ static ScsMatrix *read_amatrix(FILE *fin) {
103
103
  ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
104
104
  fread(&(A->m), sizeof(scs_int), 1, fin);
105
105
  fread(&(A->n), sizeof(scs_int), 1, fin);
106
- A->p = scs_calloc(A->n + 1, sizeof(scs_int));
106
+ A->p = (scs_int *)scs_calloc(A->n + 1, sizeof(scs_int));
107
107
  fread(A->p, sizeof(scs_int), A->n + 1, fin);
108
108
  Anz = A->p[A->n];
109
- A->x = scs_calloc(Anz, sizeof(scs_float));
110
- A->i = scs_calloc(Anz, sizeof(scs_int));
109
+ A->x = (scs_float *)scs_calloc(Anz, sizeof(scs_float));
110
+ A->i = (scs_int *)scs_calloc(Anz, sizeof(scs_int));
111
111
  fread(A->x, sizeof(scs_float), Anz, fin);
112
112
  fread(A->i, sizeof(scs_int), Anz, fin);
113
113
  return A;
@@ -132,8 +132,8 @@ static ScsData *read_scs_data(FILE *fin) {
132
132
  ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
133
133
  fread(&(d->m), sizeof(scs_int), 1, fin);
134
134
  fread(&(d->n), sizeof(scs_int), 1, fin);
135
- d->b = scs_calloc(d->m, sizeof(scs_float));
136
- d->c = scs_calloc(d->n, sizeof(scs_float));
135
+ d->b = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
136
+ d->c = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
137
137
  fread(d->b, sizeof(scs_float), d->m, fin);
138
138
  fread(d->c, sizeof(scs_float), d->n, fin);
139
139
  d->A = read_amatrix(fin);
@@ -146,8 +146,8 @@ static ScsData *read_scs_data(FILE *fin) {
146
146
  void SCS(write_data)(const ScsData *d, const ScsCone *k,
147
147
  const ScsSettings *stgs) {
148
148
  FILE *fout = fopen(stgs->write_data_filename, "wb");
149
- uint32_t scs_int_sz = (uint32_t)SCS(sizeof_int)();
150
- uint32_t scs_float_sz = (uint32_t)SCS(sizeof_float)();
149
+ uint32_t scs_int_sz = (uint32_t)sizeof(scs_int);
150
+ uint32_t scs_float_sz = (uint32_t)sizeof(scs_float);
151
151
  const char *scs_version = SCS_VERSION;
152
152
  uint32_t scs_version_sz = (uint32_t)strlen(scs_version);
153
153
  scs_printf("writing data to %s\n", stgs->write_data_filename);
@@ -213,6 +213,8 @@ void SCS(log_data_to_csv)(const ScsData *d, const ScsCone *k,
213
213
  scs_int iter, SCS(timer) * solve_timer) {
214
214
  ScsResiduals *r = w->r_orig;
215
215
  ScsResiduals *r_n = w->r_normalized;
216
+ ScsSolution *sol = w->xys_orig;
217
+ ScsSolution *sol_n = w->xys_normalized;
216
218
  /* if iter 0 open to write, else open to append */
217
219
  FILE *fout = fopen(stgs->log_csv_filename, iter == 0 ? "w" : "a");
218
220
  if (!fout) {
@@ -227,6 +229,18 @@ void SCS(log_data_to_csv)(const ScsData *d, const ScsCone *k,
227
229
  "res_pri,"
228
230
  "res_dual,"
229
231
  "gap,"
232
+ "x_nrm_inf,"
233
+ "y_nrm_inf,"
234
+ "s_nrm_inf,"
235
+ "x_nrm_2,"
236
+ "y_nrm_2,"
237
+ "s_nrm_2,"
238
+ "x_nrm_inf_normalized,"
239
+ "y_nrm_inf_normalized,"
240
+ "s_nrm_inf_normalized,"
241
+ "x_nrm_2_normalized,"
242
+ "y_nrm_2_normalized,"
243
+ "s_nrm_2_normalized,"
230
244
  "ax_s_btau_nrm_inf,"
231
245
  "px_aty_ctau_nrm_inf,"
232
246
  "ax_s_btau_nrm_2,"
@@ -252,6 +266,11 @@ void SCS(log_data_to_csv)(const ScsData *d, const ScsCone *k,
252
266
  "dobj_normalized,"
253
267
  "tau_normalized,"
254
268
  "kap_normalized,"
269
+ "ax_nrm_inf,"
270
+ "px_nrm_inf,"
271
+ "aty_nrm_inf,"
272
+ "b_nrm_inf,"
273
+ "c_nrm_inf,"
255
274
  "scale,"
256
275
  "diff_u_ut_nrm_2,"
257
276
  "diff_v_v_prev_nrm_2,"
@@ -267,6 +286,18 @@ void SCS(log_data_to_csv)(const ScsData *d, const ScsCone *k,
267
286
  fprintf(fout, "%.16e,", r->res_pri);
268
287
  fprintf(fout, "%.16e,", r->res_dual);
269
288
  fprintf(fout, "%.16e,", r->gap);
289
+ fprintf(fout, "%.16e,", SCS(norm_inf)(sol->x, w->n));
290
+ fprintf(fout, "%.16e,", SCS(norm_inf)(sol->y, w->m));
291
+ fprintf(fout, "%.16e,", SCS(norm_inf)(sol->s, w->m));
292
+ fprintf(fout, "%.16e,", SCS(norm_2)(sol->x, w->n));
293
+ fprintf(fout, "%.16e,", SCS(norm_2)(sol->y, w->m));
294
+ fprintf(fout, "%.16e,", SCS(norm_2)(sol->s, w->m));
295
+ fprintf(fout, "%.16e,", SCS(norm_inf)(sol_n->x, w->n));
296
+ fprintf(fout, "%.16e,", SCS(norm_inf)(sol_n->y, w->m));
297
+ fprintf(fout, "%.16e,", SCS(norm_inf)(sol_n->s, w->m));
298
+ fprintf(fout, "%.16e,", SCS(norm_2)(sol_n->x, w->n));
299
+ fprintf(fout, "%.16e,", SCS(norm_2)(sol_n->y, w->m));
300
+ fprintf(fout, "%.16e,", SCS(norm_2)(sol_n->s, w->m));
270
301
  fprintf(fout, "%.16e,", SCS(norm_inf)(r->ax_s_btau, w->m));
271
302
  fprintf(fout, "%.16e,", SCS(norm_inf)(r->px_aty_ctau, w->n));
272
303
  fprintf(fout, "%.16e,", SCS(norm_2)(r->ax_s_btau, w->m));
@@ -292,6 +323,11 @@ void SCS(log_data_to_csv)(const ScsData *d, const ScsCone *k,
292
323
  fprintf(fout, "%.16e,", r_n->dobj);
293
324
  fprintf(fout, "%.16e,", r_n->tau);
294
325
  fprintf(fout, "%.16e,", r_n->kap);
326
+ fprintf(fout, "%.16e,", SCS(norm_inf)(r->ax, w->m));
327
+ fprintf(fout, "%.16e,", SCS(norm_inf)(r->px, w->n));
328
+ fprintf(fout, "%.16e,", SCS(norm_inf)(r->aty, w->n));
329
+ fprintf(fout, "%.16e,", SCS(norm_inf)(w->b_orig, w->m));
330
+ fprintf(fout, "%.16e,", SCS(norm_inf)(w->c_orig, w->n));
295
331
  fprintf(fout, "%.16e,", w->scale);
296
332
  fprintf(fout, "%.16e,", SCS(norm_diff)(w->u, w->u_t, l));
297
333
  fprintf(fout, "%.16e,", SCS(norm_diff)(w->v, w->v_prev, l));