osqp 0.2.1 → 0.2.2

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: 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