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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db74c6ffd6696e799a18d2f5d02f5b753020a2535e539cdd26abac388f1ea046
4
- data.tar.gz: f7d5b3b98b58d812fb923193303b7f0bfcf7cb2972de2ae34a392fb9f4a5bd40
3
+ metadata.gz: 9005db60b3ebc21bfe74e18fbd90db752801cce6232c5dcbbf9746ed6a3772b9
4
+ data.tar.gz: 8d1eade7f1501cbf46e820a2e7b20133f008e14d2bcc098629643a9b750b55b3
5
5
  SHA512:
6
- metadata.gz: cf7a4948ba7a21865142a421da3e683904951faf7e602d429722cf05bdbae559dcc15484e6cb4afa6bf683ecf681757370bfa3fa7b01dab6620b300462eea703
7
- data.tar.gz: 493da1d4fbe2fdb7180fffad3599137500d437b082d788365bf828dd8845469b3bf0d63863ea467c013cc2f874c5b04ab935c7129d45b1c890278dda7ad21039
6
+ metadata.gz: 98ecf4f8beb7215e0ca44a57e3345b257054948c311e8e749f31d698e27c7f6c66ccbaaa71bbb091a92d4a23809b9b98a5d65767ee8d58e78cc7a8f08a32e042
7
+ data.tar.gz: 4701d88bad2ae68509fba757a922019400a78f8d8c2bdf0e33f35f7e409c49b0e8306d0cc3281a542508e3a73176042bf16a6039aee5101430ff378689791686
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 0.4.1 (2023-04-09)
2
+
3
+ - Updated SCS to 3.2.3
4
+
5
+ ## 0.4.0 (2022-07-06)
6
+
7
+ - Updated SCS to 3.2.0
8
+ - Added `Matrix` class
9
+ - Dropped support for Ruby < 2.7
10
+
1
11
  ## 0.3.2 (2022-01-17)
2
12
 
3
13
  - Updated SCS to 3.1.1
data/LICENSE.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  The MIT License (MIT)
2
2
 
3
3
  Copyright (c) 2012 Brendan O'Donoghue (bodonoghue85@gmail.com)
4
- Copyright (c) 2019-2021 Andrew Kane
4
+ Copyright (c) 2019-2023 Andrew Kane
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [SCS](https://github.com/cvxgrp/scs) - the splitting conic solver - for Ruby
4
4
 
5
- :fire: Supports many different [problem types](https://www.cvxpy.org/tutorial/advanced/index.html#choosing-a-solver)
5
+ Check out [Opt](https://github.com/ankane/opt) for a high-level interface
6
6
 
7
7
  [![Build Status](https://github.com/ankane/scs-ruby/workflows/build/badge.svg?branch=master)](https://github.com/ankane/scs-ruby/actions)
8
8
 
@@ -18,11 +18,16 @@ If installation fails, you may need to install [dependencies](#dependencies).
18
18
 
19
19
  ## Getting Started
20
20
 
21
- Prep the problem
21
+ Prep the problem, like [this one](https://www.cvxgrp.org/scs/examples/python/basic_qp.html)
22
22
 
23
23
  ```ruby
24
- data = {a: [[1], [-1]], b: [1, 0], c: [-1]}
25
- cone = {q: [], l: 2}
24
+ data = {
25
+ p: SCS::Matrix.from_dense([[3, -1], [-1, 2]]),
26
+ a: SCS::Matrix.from_dense([[-1, 1], [1, 0], [0, 1]]),
27
+ b: [-1, 0.3, -0.5],
28
+ c: [-1, -1]
29
+ }
30
+ cone = {z: 1, l: 2}
26
31
  ```
27
32
 
28
33
  And solve it
@@ -32,12 +37,36 @@ solver = SCS::Solver.new
32
37
  solver.solve(data, cone)
33
38
  ```
34
39
 
40
+ ## Data
41
+
42
+ Matrices can be a sparse matrix
43
+
44
+ ```ruby
45
+ a = SCS::Matrix.new(3, 2)
46
+ a[0, 0] = 1
47
+ a[1, 0] = 2
48
+ # or
49
+ SCS::Matrix.from_dense([[1, 0], [2, 0], [0, 0]])
50
+ ```
51
+
52
+ Arrays can be Ruby arrays
53
+
54
+ ```ruby
55
+ [1, 2, 3]
56
+ ```
57
+
58
+ Or Numo arrays
59
+
60
+ ```ruby
61
+ Numo::NArray.cast([1, 2, 3])
62
+ ```
63
+
35
64
  ## Settings
36
65
 
37
66
  Default values shown
38
67
 
39
68
  ```ruby
40
- solver.solve(data, cone, {
69
+ solver.solve(data, cone,
41
70
  normalize: true, # heuristic data rescaling
42
71
  scale: 0.1, # if normalized, rescales by this factor
43
72
  adaptive_scale: true, # heuristically adapt dual scale through the solve
@@ -54,7 +83,7 @@ solver.solve(data, cone, {
54
83
  acceleration_interval: 10, # iterations to run Anderson acceleration
55
84
  write_data_filename: nil, # filename to write data if set
56
85
  log_csv_filename: nil # write csv logs of various quantities
57
- })
86
+ )
58
87
  ```
59
88
 
60
89
  ## Direct vs Indirect
data/lib/scs/matrix.rb ADDED
@@ -0,0 +1,72 @@
1
+ module SCS
2
+ class Matrix
3
+ attr_reader :m, :n
4
+
5
+ def initialize(m, n)
6
+ @m = m
7
+ @n = n
8
+ @data = {}
9
+ end
10
+
11
+ def []=(row_index, column_index, value)
12
+ raise IndexError, "row index out of bounds" if row_index < 0 || row_index >= @m
13
+ raise IndexError, "column index out of bounds" if column_index < 0 || column_index >= @n
14
+ # dictionary of keys, optimized for converting to CSC
15
+ # TODO try COO for performance
16
+ if value == 0
17
+ (@data[column_index] ||= {}).delete(row_index)
18
+ else
19
+ (@data[column_index] ||= {})[row_index] = value
20
+ end
21
+ end
22
+
23
+ def to_csc
24
+ cx = []
25
+ ci = []
26
+ cp = []
27
+
28
+ # CSC format
29
+ # https://www.gormanalysis.com/blog/sparse-matrix-storage-formats/
30
+ cp << 0
31
+ n.times do |j|
32
+ (@data[j] || {}).sort_by { |k, v| k }.each do |k, v|
33
+ cx << v
34
+ ci << k
35
+ end
36
+ # cumulative column values
37
+ cp << cx.size
38
+ end
39
+
40
+ {
41
+ start: cp,
42
+ index: ci,
43
+ value: cx
44
+ }
45
+ end
46
+
47
+ # private, for tests
48
+ def nnz
49
+ @data.sum { |_, v| v.count }
50
+ end
51
+
52
+ def initialize_copy(other)
53
+ super
54
+ @data = @data.transform_values(&:dup)
55
+ end
56
+
57
+ def self.from_dense(data)
58
+ data = data.to_a
59
+ m = data.size
60
+ n = m > 0 ? data.first.size : 0
61
+
62
+ mtx = Matrix.new(m, n)
63
+ data.each_with_index do |row, i|
64
+ raise ArgumentError, "row has different number of columns" if row.size != n
65
+ row.each_with_index do |v, j|
66
+ mtx[i, j] = v if v != 0
67
+ end
68
+ end
69
+ mtx
70
+ end
71
+ end
72
+ end
data/lib/scs/solver.rb CHANGED
@@ -73,42 +73,35 @@ module SCS
73
73
  char_ptr[0, idx].map(&:chr).join
74
74
  end
75
75
 
76
- # TODO add support sparse matrices
77
76
  def csc_matrix(mtx, upper: false)
78
- mtx = mtx.to_a
79
-
80
- m, n = shape(mtx)
81
-
82
- cx = []
83
- ci = []
84
- cp = []
85
-
86
- # CSC format
87
- # https://www.gormanalysis.com/blog/sparse-matrix-storage-formats/
88
- cp << 0
89
- n.times do |j|
90
- mtx.each_with_index do |row, i|
91
- if row[j] != 0 && (!upper || i <= j)
92
- cx << row[j]
93
- ci << i
77
+ mtx = Matrix.from_dense(mtx) unless mtx.is_a?(Matrix)
78
+
79
+ if upper
80
+ # TODO improve performance
81
+ mtx = mtx.dup
82
+ mtx.m.times do |i|
83
+ mtx.n.times do |j|
84
+ mtx[i, j] = 0 if i > j
94
85
  end
95
86
  end
96
- # cumulative column values
97
- cp << cx.size
98
87
  end
99
88
 
89
+ csc = mtx.to_csc
90
+
100
91
  # construct matrix
101
92
  matrix = ffi::Matrix.malloc
102
- matrix.x = float_array(cx)
103
- matrix.i = int_array(ci)
104
- matrix.p = int_array(cp)
105
- matrix.m = m
106
- matrix.n = n
93
+ matrix.x = float_array(csc[:value])
94
+ matrix.i = int_array(csc[:index])
95
+ matrix.p = int_array(csc[:start])
96
+ matrix.m = mtx.m
97
+ matrix.n = mtx.n
107
98
  matrix
108
99
  end
109
100
 
110
101
  def shape(a)
111
- if defined?(Matrix) && a.is_a?(Matrix)
102
+ if a.is_a?(Matrix)
103
+ [a.m, a.n]
104
+ elsif defined?(::Matrix) && a.is_a?(::Matrix)
112
105
  [a.row_count, a.column_count]
113
106
  elsif defined?(Numo::NArray) && a.is_a?(Numo::NArray)
114
107
  a.shape
@@ -126,7 +119,7 @@ module SCS
126
119
 
127
120
  if data[:p]
128
121
  raise ArgumentError, "Bad p shape" if shape(data[:p]) != [n, n]
129
- cdata.p = csc_matrix(data[:p])
122
+ cdata.p = csc_matrix(data[:p], upper: true)
130
123
  end
131
124
 
132
125
  raise ArgumentError, "Bad b size" if data[:b].to_a.size != m
data/lib/scs/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module SCS
2
- VERSION = "0.3.2"
2
+ VERSION = "0.4.1"
3
3
  end
data/lib/scs.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  require "fiddle/import"
3
3
 
4
4
  # modules
5
+ require "scs/matrix"
5
6
  require "scs/solver"
6
7
  require "scs/version"
7
8
 
@@ -10,8 +10,8 @@ authors:
10
10
  - family-names: "Boyd"
11
11
  given-names: "Stephen"
12
12
  title: "SCS: Spltting Conic Solver"
13
- version: 3.1.1
14
- date-released: 2021
13
+ version: 3.2.3
14
+ date-released: 2023
15
15
  url: "https://github.com/cvxgrp/scs"
16
16
 
17
17
  # Original SCS paper: