lib/osqp/solver.rb in osqp-0.2.0 vs lib/osqp/solver.rb in osqp-0.2.1
- old
+ new
@@ -8,20 +8,19 @@
l = l.map { |v| v < -FFI::OSQP_INFTY ? -FFI::OSQP_INFTY : v }
u = u.map { |v| v > FFI::OSQP_INFTY ? FFI::OSQP_INFTY : v }
# data
# do not assign directly to struct to keep refs
- m, n = shape(a)
p = csc_matrix(p, upper: true)
- q = float_array(q)
+ q = Utils.float_array(q)
a = csc_matrix(a)
- l = float_array(l)
- u = float_array(u)
+ l = Utils.float_array(l)
+ u = Utils.float_array(u)
data = FFI::Data.malloc
- data.n = n
- data.m = m
+ data.n = a.n
+ data.m = a.m
data.p = p
data.q = q
data.a = a
data.l = l
data.u = u
@@ -72,15 +71,15 @@
m, n = dimensions
raise Error, "Expected x to be size #{n}, got #{x.size}" if x && x.size != n
raise Error, "Expected y to be size #{m}, got #{y.size}" if y && y.size != m
if x && y
- check_result FFI.osqp_warm_start(@work, float_array(x), float_array(y))
+ check_result FFI.osqp_warm_start(@work, Utils.float_array(x), Utils.float_array(y))
elsif x
- check_result FFI.osqp_warm_start_x(@work, float_array(x))
+ check_result FFI.osqp_warm_start_x(@work, Utils.float_array(x))
elsif y
- check_result FFI.osqp_warm_start_y(@work, float_array(y))
+ check_result FFI.osqp_warm_start_y(@work, Utils.float_array(y))
else
raise Error, "Must set x or y"
end
end
@@ -112,77 +111,36 @@
raise Error, message
end
end
- def float_array(arr)
- # OSQP float = double
- Fiddle::Pointer[arr.to_a.pack("d*")]
- end
-
- def int_array(arr)
- # OSQP int = long long
- Fiddle::Pointer[arr.to_a.pack("q*")]
- end
-
def read_float_array(ptr, size)
# OSQP float = double
ptr[0, size * Fiddle::SIZEOF_DOUBLE].unpack("d*")
end
def read_string(char_ptr)
idx = char_ptr.index { |v| v == 0 }
char_ptr[0, idx].map(&:chr).join
end
- # TODO add support sparse matrices
def csc_matrix(mtx, upper: false)
- mtx = mtx.to_a
+ mtx = Matrix.from_dense(mtx) unless mtx.is_a?(Matrix)
- m, n = shape(mtx)
-
- cx = []
- ci = []
- cp = []
-
- # CSC format
- # https://www.gormanalysis.com/blog/sparse-matrix-storage-formats/
- cp << 0
- n.times do |j|
- mtx.each_with_index do |row, i|
- if row[j] != 0 && (!upper || i <= j)
- cx << row[j]
- ci << i
+ if upper
+ mtx.m.times do |i|
+ mtx.n.times do |j|
+ mtx[i, j] = 0 if i > j
end
end
- # cumulative column values
- cp << cx.size
end
- nnz = cx.size
- cx = float_array(cx)
- ci = int_array(ci)
- cp = int_array(cp)
-
- ptr = FFI.csc_matrix(m, n, nnz, cx, ci, cp)
- # save refs
- ptr.instance_variable_set(:@osqp_refs, [cx, ci, cp])
- ptr
+ mtx
end
def dimensions
data = FFI::Data.new(@work.data)
[data.m, data.n]
- end
-
- def shape(a)
- if defined?(Matrix) && a.is_a?(Matrix)
- [a.row_count, a.column_count]
- elsif defined?(Numo::NArray) && a.is_a?(Numo::NArray)
- a.shape
- else
- [a.size, a.first.size]
- end
end
def create_settings(settings)
set = FFI::Settings.malloc
FFI.osqp_set_default_settings(set)