scs 0.3.2 → 0.4.1

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