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)