osqp 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b2906722de1daf0e3f2441edee63d8cec2452012cd9fa91634f37418e66f6fc
4
- data.tar.gz: ee0cf11cc8ea7d1676843699265ad27623d237940c756fdb9c49c8e404137b37
3
+ metadata.gz: b6ed92bcdae0ff5291f26741fc77be7da17b2dc1e4bb6680df7c20516f6b894e
4
+ data.tar.gz: 7f66c0c4d72a6bb77abb7d3cf4119d79117c92079d7b4dde460d2d952277aed1
5
5
  SHA512:
6
- metadata.gz: 835c7ac35d791e794b7da902a1a248696860ed09d05e8831d0d4b6c54615758f6d930443e1f4b4f21d0b9d10453882653db60e2bda46b107d342a3cda304e889
7
- data.tar.gz: 027ec047ca635e1b9f36377921110444a90226dfa85ebeac44ccab5b1945aac2d37f487f7725ba5604f264551f852392855e087c84afd1c39cd7790278fa3c68
6
+ metadata.gz: e16b34d395a64988f04c2779d67dfd164162940e92cbd857ae324aa694ee04e05162fd8cb9532a2a7b828d598814bff5fd4cce8601a8b29e3f69913d530085b9
7
+ data.tar.gz: f8b0dfb4a6657d7398bd3f366c8368bc82233e611890f19e603e21b45a566cd9a7b12e07cb894a669872eab28948d79df919aa973f686d980a94889f4cbdef1e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.3.0 (2024-10-23)
2
+
3
+ - Dropped support for Ruby < 3.1
4
+
5
+ ## 0.2.2 (2023-01-29)
6
+
7
+ - Fixed mutating `p` argument when not upper triangle
8
+
1
9
  ## 0.2.1 (2022-07-05)
2
10
 
3
11
  - Added `Matrix` class
data/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  The [OSQP](https://osqp.org/) (Operator Splitting Quadratic Program) solver for Ruby
4
4
 
5
- [![Build Status](https://github.com/ankane/osqp-ruby/workflows/build/badge.svg?branch=master)](https://github.com/ankane/osqp-ruby/actions)
5
+ Check out [Opt](https://github.com/ankane/opt) for a high-level interface
6
+
7
+ [![Build Status](https://github.com/ankane/osqp-ruby/actions/workflows/build.yml/badge.svg)](https://github.com/ankane/osqp-ruby/actions)
6
8
 
7
9
  ## Installation
8
10
 
data/lib/osqp/matrix.rb CHANGED
@@ -11,6 +11,8 @@ module OSQP
11
11
  def []=(row_index, column_index, value)
12
12
  raise IndexError, "row index out of bounds" if row_index < 0 || row_index >= @m
13
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
14
16
  if value == 0
15
17
  (@data[column_index] ||= {}).delete(row_index)
16
18
  else
@@ -18,7 +20,7 @@ module OSQP
18
20
  end
19
21
  end
20
22
 
21
- def to_ptr
23
+ def to_csc
22
24
  cx = []
23
25
  ci = []
24
26
  cp = []
@@ -35,15 +37,21 @@ module OSQP
35
37
  cp << cx.size
36
38
  end
37
39
 
38
- nnz = cx.size
39
- cx = Utils.float_array(cx)
40
- ci = Utils.int_array(ci)
41
- cp = Utils.int_array(cp)
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
42
51
 
43
- ptr = FFI.csc_matrix(m, n, nnz, cx, ci, cp)
44
- # save refs
45
- ptr.instance_variable_set(:@osqp_refs, [cx, ci, cp])
46
- ptr
52
+ def initialize_copy(other)
53
+ super
54
+ @data = @data.transform_values(&:dup)
47
55
  end
48
56
 
49
57
  def self.from_dense(data)
data/lib/osqp/solver.rb CHANGED
@@ -11,17 +11,17 @@ module OSQP
11
11
  # data
12
12
  # do not assign directly to struct to keep refs
13
13
  p = csc_matrix(p, upper: true)
14
- q = Utils.float_array(q)
14
+ q = float_array(q)
15
15
  a = csc_matrix(a)
16
- l = Utils.float_array(l)
17
- u = Utils.float_array(u)
16
+ l = float_array(l)
17
+ u = float_array(u)
18
18
 
19
19
  data = FFI::Data.malloc
20
20
  data.n = a.n
21
21
  data.m = a.m
22
- data.p = p
22
+ data.p = matrix_ptr(p)
23
23
  data.q = q
24
- data.a = a
24
+ data.a = matrix_ptr(a)
25
25
  data.l = l
26
26
  data.u = u
27
27
 
@@ -73,11 +73,11 @@ module OSQP
73
73
  raise Error, "Expected y to be size #{m}, got #{y.size}" if y && y.size != m
74
74
 
75
75
  if x && y
76
- check_result FFI.osqp_warm_start(@work, Utils.float_array(x), Utils.float_array(y))
76
+ check_result FFI.osqp_warm_start(@work, float_array(x), float_array(y))
77
77
  elsif x
78
- check_result FFI.osqp_warm_start_x(@work, Utils.float_array(x))
78
+ check_result FFI.osqp_warm_start_x(@work, float_array(x))
79
79
  elsif y
80
- check_result FFI.osqp_warm_start_y(@work, Utils.float_array(y))
80
+ check_result FFI.osqp_warm_start_y(@work, float_array(y))
81
81
  else
82
82
  raise Error, "Must set x or y"
83
83
  end
@@ -113,6 +113,16 @@ module OSQP
113
113
  end
114
114
  end
115
115
 
116
+ def float_array(arr)
117
+ # OSQP float = double
118
+ Fiddle::Pointer[arr.to_a.pack("d*")]
119
+ end
120
+
121
+ def int_array(arr)
122
+ # OSQP int = long long
123
+ Fiddle::Pointer[arr.to_a.pack("q*")]
124
+ end
125
+
116
126
  def read_float_array(ptr, size)
117
127
  # OSQP float = double
118
128
  ptr[0, size * Fiddle::SIZEOF_DOUBLE].unpack("d*")
@@ -127,6 +137,8 @@ module OSQP
127
137
  mtx = Matrix.from_dense(mtx) unless mtx.is_a?(Matrix)
128
138
 
129
139
  if upper
140
+ # TODO improve performance
141
+ mtx = mtx.dup
130
142
  mtx.m.times do |i|
131
143
  mtx.n.times do |j|
132
144
  mtx[i, j] = 0 if i > j
@@ -137,6 +149,19 @@ module OSQP
137
149
  mtx
138
150
  end
139
151
 
152
+ def matrix_ptr(mtx)
153
+ csc = mtx.to_csc
154
+ nnz = csc[:value].size
155
+ cx = float_array(csc[:value])
156
+ ci = int_array(csc[:index])
157
+ cp = int_array(csc[:start])
158
+
159
+ ptr = FFI.csc_matrix(mtx.m, mtx.n, nnz, cx, ci, cp)
160
+ # save refs
161
+ ptr.instance_variable_set(:@osqp_refs, [cx, ci, cp])
162
+ ptr
163
+ end
164
+
140
165
  def dimensions
141
166
  data = FFI::Data.new(@work.data)
142
167
  [data.m, data.n]
data/lib/osqp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module OSQP
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/osqp.rb CHANGED
@@ -4,7 +4,6 @@ require "fiddle/import"
4
4
  # modules
5
5
  require "osqp/matrix"
6
6
  require "osqp/solver"
7
- require "osqp/utils"
8
7
  require "osqp/version"
9
8
 
10
9
  module OSQP
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: osqp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-05 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2024-10-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fiddle
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  description:
14
28
  email: andrew@ankane.org
15
29
  executables: []
@@ -63,14 +77,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
77
  requirements:
64
78
  - - ">="
65
79
  - !ruby/object:Gem::Version
66
- version: '2.7'
80
+ version: '3.1'
67
81
  required_rubygems_version: !ruby/object:Gem::Requirement
68
82
  requirements:
69
83
  - - ">="
70
84
  - !ruby/object:Gem::Version
71
85
  version: '0'
72
86
  requirements: []
73
- rubygems_version: 3.3.7
87
+ rubygems_version: 3.5.16
74
88
  signing_key:
75
89
  specification_version: 4
76
90
  summary: OSQP (Operator Splitting Quadratic Program) solver for Ruby