scs 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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));