osqp 0.2.1 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b2906722de1daf0e3f2441edee63d8cec2452012cd9fa91634f37418e66f6fc
4
- data.tar.gz: ee0cf11cc8ea7d1676843699265ad27623d237940c756fdb9c49c8e404137b37
3
+ metadata.gz: f94b0363a8ee43efba253d1138642c54832aed26cd2bc7d8e4bfb064453754fd
4
+ data.tar.gz: 673f1fa4d56747e26e0ab36cdd642c21d2c0d93c6233bb37502cfff805421d54
5
5
  SHA512:
6
- metadata.gz: 835c7ac35d791e794b7da902a1a248696860ed09d05e8831d0d4b6c54615758f6d930443e1f4b4f21d0b9d10453882653db60e2bda46b107d342a3cda304e889
7
- data.tar.gz: 027ec047ca635e1b9f36377921110444a90226dfa85ebeac44ccab5b1945aac2d37f487f7725ba5604f264551f852392855e087c84afd1c39cd7790278fa3c68
6
+ metadata.gz: 4af98ca5b0b140d3f20e82b64220583f3a0b720a45da74ea25ff4ca6b1921188d14ef12c8f4fb87e171c55f3e166ac8572c6856e94aae484687b8193e90ee6c2
7
+ data.tar.gz: df8999d0333e4467223931e89e5ad1b88567dca38f502a387e1077f21a652fdf86ab6c5171c56d030122eeba85f4265eba9d1737481a7f79a77cc8e6a1fe410e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.2.2 (2023-01-29)
2
+
3
+ - Fixed mutating `p` argument when not upper triangle
4
+
1
5
  ## 0.2.1 (2022-07-05)
2
6
 
3
7
  - Added `Matrix` class
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  The [OSQP](https://osqp.org/) (Operator Splitting Quadratic Program) solver for Ruby
4
4
 
5
+ Check out [Opt](https://github.com/ankane/opt) for a high-level interface
6
+
5
7
  [![Build Status](https://github.com/ankane/osqp-ruby/workflows/build/badge.svg?branch=master)](https://github.com/ankane/osqp-ruby/actions)
6
8
 
7
9
  ## Installation
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.2.2"
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,14 +1,14 @@
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.2.2
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
11
+ date: 2023-01-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: andrew@ankane.org
@@ -70,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
70
  - !ruby/object:Gem::Version
71
71
  version: '0'
72
72
  requirements: []
73
- rubygems_version: 3.3.7
73
+ rubygems_version: 3.4.1
74
74
  signing_key:
75
75
  specification_version: 4
76
76
  summary: OSQP (Operator Splitting Quadratic Program) solver for Ruby