scs 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 +7 -0
- data/CHANGELOG.md +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +98 -0
- data/ext/scs/extconf.rb +29 -0
- data/lib/scs.rb +17 -0
- data/lib/scs/ffi.rb +117 -0
- data/lib/scs/solver.rb +173 -0
- data/lib/scs/version.rb +3 -0
- data/vendor/scs/LICENSE.txt +21 -0
- data/vendor/scs/Makefile +164 -0
- data/vendor/scs/README.md +222 -0
- data/vendor/scs/include/aa.h +56 -0
- data/vendor/scs/include/cones.h +46 -0
- data/vendor/scs/include/ctrlc.h +33 -0
- data/vendor/scs/include/glbopts.h +177 -0
- data/vendor/scs/include/linalg.h +26 -0
- data/vendor/scs/include/linsys.h +64 -0
- data/vendor/scs/include/normalize.h +18 -0
- data/vendor/scs/include/rw.h +17 -0
- data/vendor/scs/include/scs.h +161 -0
- data/vendor/scs/include/scs_blas.h +51 -0
- data/vendor/scs/include/util.h +65 -0
- data/vendor/scs/linsys/amatrix.c +305 -0
- data/vendor/scs/linsys/amatrix.h +36 -0
- data/vendor/scs/linsys/amatrix.o +0 -0
- data/vendor/scs/linsys/cpu/direct/private.c +366 -0
- data/vendor/scs/linsys/cpu/direct/private.h +26 -0
- data/vendor/scs/linsys/cpu/direct/private.o +0 -0
- data/vendor/scs/linsys/cpu/indirect/private.c +256 -0
- data/vendor/scs/linsys/cpu/indirect/private.h +31 -0
- data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
- data/vendor/scs/linsys/external/amd/LICENSE.txt +934 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +469 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +254 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
- data/vendor/scs/linsys/external/amd/amd.h +400 -0
- data/vendor/scs/linsys/external/amd/amd_1.c +180 -0
- data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_2.c +1842 -0
- data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_aat.c +184 -0
- data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_control.c +64 -0
- data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_defaults.c +37 -0
- data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_dump.c +179 -0
- data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_global.c +16 -0
- data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_info.c +119 -0
- data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_internal.h +304 -0
- data/vendor/scs/linsys/external/amd/amd_order.c +199 -0
- data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_post_tree.c +120 -0
- data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_postorder.c +206 -0
- data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_preprocess.c +118 -0
- data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_valid.c +92 -0
- data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
- data/vendor/scs/linsys/external/amd/changes +11 -0
- data/vendor/scs/linsys/external/qdldl/LICENSE +201 -0
- data/vendor/scs/linsys/external/qdldl/README.md +120 -0
- data/vendor/scs/linsys/external/qdldl/changes +4 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.c +298 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.h +177 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
- data/vendor/scs/linsys/external/qdldl/qdldl_types.h +21 -0
- data/vendor/scs/linsys/gpu/gpu.c +41 -0
- data/vendor/scs/linsys/gpu/gpu.h +85 -0
- data/vendor/scs/linsys/gpu/indirect/private.c +304 -0
- data/vendor/scs/linsys/gpu/indirect/private.h +36 -0
- data/vendor/scs/scs.mk +181 -0
- data/vendor/scs/src/aa.c +224 -0
- data/vendor/scs/src/aa.o +0 -0
- data/vendor/scs/src/cones.c +802 -0
- data/vendor/scs/src/cones.o +0 -0
- data/vendor/scs/src/ctrlc.c +77 -0
- data/vendor/scs/src/ctrlc.o +0 -0
- data/vendor/scs/src/linalg.c +84 -0
- data/vendor/scs/src/linalg.o +0 -0
- data/vendor/scs/src/normalize.c +93 -0
- data/vendor/scs/src/normalize.o +0 -0
- data/vendor/scs/src/rw.c +167 -0
- data/vendor/scs/src/rw.o +0 -0
- data/vendor/scs/src/scs.c +978 -0
- data/vendor/scs/src/scs.o +0 -0
- data/vendor/scs/src/scs_version.c +5 -0
- data/vendor/scs/src/scs_version.o +0 -0
- data/vendor/scs/src/util.c +196 -0
- data/vendor/scs/src/util.o +0 -0
- data/vendor/scs/test/data/small_random_socp +0 -0
- data/vendor/scs/test/minunit.h +13 -0
- data/vendor/scs/test/problem_utils.h +93 -0
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +85 -0
- data/vendor/scs/test/problems/small_lp.h +50 -0
- data/vendor/scs/test/problems/small_random_socp.h +33 -0
- data/vendor/scs/test/random_socp_prob.c +171 -0
- data/vendor/scs/test/run_from_file.c +69 -0
- data/vendor/scs/test/run_tests +2 -0
- data/vendor/scs/test/run_tests.c +32 -0
- metadata +203 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: cf0730fd042983c36ce96ea46ad28c0a330c5765e1521f8cfb28eb3321507df9
|
|
4
|
+
data.tar.gz: 677ebb1dc72dc2c1e51857c8644a11e91f9a332c95574ee8c452e31f36f4ec88
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 889d538aba521314bc093e11fc584eb58f519116f72fedcab865b9a49a44fec44eaffbc20e28d1f2673c294922474c7ccc91f7ee7f0b08243c9e20ae52150e3c
|
|
7
|
+
data.tar.gz: 25ca5f1af62a227f1f05c34031d8f1554e1b9121c2d8c43bb40c4bd12d0af5d106b73a601f8abb8a3849fbdcde310b51a2fecfe17bb9e4bba4d3a70e5fd59fff
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2019-2020 Andrew Kane
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# SCS
|
|
2
|
+
|
|
3
|
+
[SCS](https://github.com/cvxgrp/scs) - the splitting conic solver - for Ruby
|
|
4
|
+
|
|
5
|
+
:fire: Supports many different [problem types](https://www.cvxpy.org/tutorial/advanced/index.html#choosing-a-solver)
|
|
6
|
+
|
|
7
|
+
[](https://travis-ci.org/ankane/scs) [](https://ci.appveyor.com/project/ankane/scs/branch/master)
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Add this line to your application’s Gemfile:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
gem 'scs'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
If installation fails, you may need to install [dependencies](#dependencies).
|
|
18
|
+
|
|
19
|
+
## Getting Started
|
|
20
|
+
|
|
21
|
+
Prep the problem
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
data = {a: [[1], [-1]], b: [1, 0], c: [-1]}
|
|
25
|
+
cone = {q: [], l: 2}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
And solve it
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
solver = SCS::Solver.new
|
|
32
|
+
solver.solve(data, cone)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Settings
|
|
36
|
+
|
|
37
|
+
Default values shown
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
solver.solve(data, cone, {
|
|
41
|
+
normalize: true, # heuristic data rescaling
|
|
42
|
+
scale: 1.0, # if normalized, rescales by this factor
|
|
43
|
+
rho_x: 1e-3, # x equality constraint scaling
|
|
44
|
+
max_iters: 5000, # maximum iterations to take
|
|
45
|
+
eps: 1e-5, # convergence tolerance
|
|
46
|
+
alpha: 1.5, # relaxation parameter
|
|
47
|
+
cg_rate: 2.0, # for indirect, tolerance goes down like (1/iter)^cg_rate
|
|
48
|
+
verbose: true, # write out progress
|
|
49
|
+
warm_start: false, # warm start
|
|
50
|
+
acceleration_lookback: 10, # memory for acceleration
|
|
51
|
+
write_data_filename: nil # filename to write data if set
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Direct vs Indirect
|
|
56
|
+
|
|
57
|
+
SCS comes with two solvers: a direct solver which uses a cached LDL factorization and an indirect solver based on conjugate gradients. For the indirect solver, use:
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
SCS::Solver.new(indirect: true)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Dependencies
|
|
64
|
+
|
|
65
|
+
BLAS and LAPACK are required for SCS.
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
sudo apt-get install libblas-dev liblapack-dev
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
On Heroku, use the [heroku-apt-buildpack](https://github.com/heroku/heroku-buildpack-apt).
|
|
72
|
+
|
|
73
|
+
## Resources
|
|
74
|
+
|
|
75
|
+
- [Conic Optimization via Operator Splitting and Homogeneous Self-Dual Embedding](https://web.stanford.edu/~boyd/papers/scs.html)
|
|
76
|
+
|
|
77
|
+
## History
|
|
78
|
+
|
|
79
|
+
View the [changelog](https://github.com/ankane/scs/blob/master/CHANGELOG.md)
|
|
80
|
+
|
|
81
|
+
## Contributing
|
|
82
|
+
|
|
83
|
+
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
|
84
|
+
|
|
85
|
+
- [Report bugs](https://github.com/ankane/scs/issues)
|
|
86
|
+
- Fix bugs and [submit pull requests](https://github.com/ankane/scs/pulls)
|
|
87
|
+
- Write, clarify, or fix documentation
|
|
88
|
+
- Suggest or add new features
|
|
89
|
+
|
|
90
|
+
To get started with development:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
git clone --recursive https://github.com/ankane/scs.git
|
|
94
|
+
cd scs
|
|
95
|
+
bundle install
|
|
96
|
+
bundle exec rake compile
|
|
97
|
+
bundle exec rake test
|
|
98
|
+
```
|
data/ext/scs/extconf.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require "mkmf"
|
|
2
|
+
|
|
3
|
+
def run(command)
|
|
4
|
+
puts ">> #{command}"
|
|
5
|
+
unless system(command)
|
|
6
|
+
raise "Command failed"
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def inreplace(file, pattern, replacement)
|
|
11
|
+
contents = File.read(file)
|
|
12
|
+
File.write(file, contents.gsub(pattern, replacement))
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
arch = RbConfig::CONFIG["arch"]
|
|
16
|
+
puts "Arch: #{arch}"
|
|
17
|
+
|
|
18
|
+
scs = File.expand_path("../../vendor/scs", __dir__)
|
|
19
|
+
Dir.chdir(scs) do
|
|
20
|
+
case arch
|
|
21
|
+
when /mingw/
|
|
22
|
+
inreplace("scs.mk", "USE_LAPACK = 1", "USE_LAPACK = 0")
|
|
23
|
+
run "ridk exec make"
|
|
24
|
+
else
|
|
25
|
+
run "make"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
File.write("Makefile", dummy_makefile("scs").join)
|
data/lib/scs.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# stdlib
|
|
2
|
+
require "fiddle/import"
|
|
3
|
+
|
|
4
|
+
# modules
|
|
5
|
+
require "scs/solver"
|
|
6
|
+
require "scs/version"
|
|
7
|
+
|
|
8
|
+
module SCS
|
|
9
|
+
class Error < StandardError; end
|
|
10
|
+
|
|
11
|
+
def self.lib_version
|
|
12
|
+
FFI::Direct.scs_version.to_s
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# friendlier error message
|
|
16
|
+
autoload :FFI, "scs/ffi"
|
|
17
|
+
end
|
data/lib/scs/ffi.rb
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
module SCS
|
|
2
|
+
module FFI
|
|
3
|
+
module Direct
|
|
4
|
+
def self.lib_name
|
|
5
|
+
"libscsdir"
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module Indirect
|
|
10
|
+
def self.lib_name
|
|
11
|
+
"libscsindir"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
ext =
|
|
16
|
+
if Gem.win_platform?
|
|
17
|
+
"dll"
|
|
18
|
+
elsif RbConfig::CONFIG["host_os"] =~ /darwin/i
|
|
19
|
+
"dylib"
|
|
20
|
+
else
|
|
21
|
+
"so"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
[Direct, Indirect].each do |m|
|
|
25
|
+
m.module_eval do
|
|
26
|
+
extend Fiddle::Importer
|
|
27
|
+
|
|
28
|
+
dlload File.expand_path("../../vendor/scs/out/#{lib_name}.#{ext}", __dir__)
|
|
29
|
+
|
|
30
|
+
extern "size_t scs_sizeof_int(void)"
|
|
31
|
+
extern "size_t scs_sizeof_float(void)"
|
|
32
|
+
|
|
33
|
+
# TODO support other sizes
|
|
34
|
+
raise Error, "Unsupported int size" if scs_sizeof_int != 4
|
|
35
|
+
raise Error, "Unsupported float size" if scs_sizeof_float != 8
|
|
36
|
+
|
|
37
|
+
typealias "scs_float", "double"
|
|
38
|
+
typealias "scs_int", "int"
|
|
39
|
+
|
|
40
|
+
m::Data = struct [
|
|
41
|
+
"scs_int m",
|
|
42
|
+
"scs_int n",
|
|
43
|
+
"ScsMatrix *a",
|
|
44
|
+
"scs_float *b",
|
|
45
|
+
"scs_float *c",
|
|
46
|
+
"ScsSettings *stgs"
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
m::Cone = struct [
|
|
50
|
+
"scs_int f",
|
|
51
|
+
"scs_int l",
|
|
52
|
+
"scs_int *q",
|
|
53
|
+
"scs_int qsize",
|
|
54
|
+
"scs_int *s",
|
|
55
|
+
"scs_int ssize",
|
|
56
|
+
"scs_int ep",
|
|
57
|
+
"scs_int ed",
|
|
58
|
+
"scs_float *p",
|
|
59
|
+
"scs_int psize",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
m::Solution = struct [
|
|
63
|
+
"scs_float *x",
|
|
64
|
+
"scs_float *y",
|
|
65
|
+
"scs_float *s"
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
m::Info = struct [
|
|
69
|
+
"scs_int iter",
|
|
70
|
+
"char status[32]",
|
|
71
|
+
"scs_int status_val",
|
|
72
|
+
"scs_float pobj",
|
|
73
|
+
"scs_float dobj",
|
|
74
|
+
"scs_float res_pri",
|
|
75
|
+
"scs_float res_dual",
|
|
76
|
+
"scs_float res_infeas",
|
|
77
|
+
"scs_float res_unbdd",
|
|
78
|
+
"scs_float rel_gap",
|
|
79
|
+
"scs_float setup_time",
|
|
80
|
+
"scs_float solve_time"
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
m::Settings = struct [
|
|
84
|
+
"scs_int normalize",
|
|
85
|
+
"scs_float scale",
|
|
86
|
+
"scs_float rho_x",
|
|
87
|
+
"scs_int max_iters",
|
|
88
|
+
"scs_float eps",
|
|
89
|
+
"scs_float alpha",
|
|
90
|
+
"scs_float cg_rate",
|
|
91
|
+
"scs_int verbose",
|
|
92
|
+
"scs_int warm_start",
|
|
93
|
+
"scs_int acceleration_lookback",
|
|
94
|
+
"const char* write_data_filename"
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
m::Matrix = struct [
|
|
98
|
+
"scs_float *x",
|
|
99
|
+
"scs_int *i",
|
|
100
|
+
"scs_int *p",
|
|
101
|
+
"scs_int m",
|
|
102
|
+
"scs_int n"
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
# scs.h
|
|
106
|
+
extern "ScsWork *scs_init(const ScsData *d, const ScsCone *k, ScsInfo *info)"
|
|
107
|
+
extern "scs_int scs_solve(ScsWork *w, const ScsData *d, const ScsCone *k, ScsSolution *sol, ScsInfo *info)"
|
|
108
|
+
extern "void scs_finish(ScsWork *w)"
|
|
109
|
+
extern "scs_int scs(const ScsData *d, const ScsCone *k, ScsSolution *sol, ScsInfo *info)"
|
|
110
|
+
extern "const char *scs_version(void)"
|
|
111
|
+
|
|
112
|
+
# utils.h
|
|
113
|
+
extern "void scs_set_default_settings(ScsData *d)"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
data/lib/scs/solver.rb
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
module SCS
|
|
2
|
+
class Solver
|
|
3
|
+
def initialize(indirect: false)
|
|
4
|
+
@ffi = indirect ? FFI::Indirect : FFI::Direct
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def solve(data, cone, **settings)
|
|
8
|
+
cdata = create_data(data)
|
|
9
|
+
set_settings(cdata, settings)
|
|
10
|
+
ccone = create_cone(cone)
|
|
11
|
+
|
|
12
|
+
solution = calloc(ffi::Solution.size) # alloc clear memory
|
|
13
|
+
info = ffi::Info.malloc
|
|
14
|
+
|
|
15
|
+
ffi.scs(cdata, ccone, solution, info)
|
|
16
|
+
|
|
17
|
+
solution = ffi::Solution.new(solution)
|
|
18
|
+
x = read_float_array(solution.x, cdata.n)
|
|
19
|
+
y = read_float_array(solution.y, cdata.m)
|
|
20
|
+
s = read_float_array(solution.s, cdata.m)
|
|
21
|
+
|
|
22
|
+
{
|
|
23
|
+
x: x,
|
|
24
|
+
y: y,
|
|
25
|
+
s: s,
|
|
26
|
+
iter: info.iter,
|
|
27
|
+
status: read_string(info.status),
|
|
28
|
+
status_val: info.status_val,
|
|
29
|
+
pobj: info.pobj,
|
|
30
|
+
dobj: info.dobj,
|
|
31
|
+
res_pri: info.res_pri,
|
|
32
|
+
res_dual: info.res_dual,
|
|
33
|
+
res_infeas: info.res_infeas,
|
|
34
|
+
res_unbdd: info.res_unbdd,
|
|
35
|
+
rel_gap: info.rel_gap,
|
|
36
|
+
setup_time: info.setup_time,
|
|
37
|
+
solve_time: info.solve_time
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def check_result(ret)
|
|
44
|
+
raise Error, "Error code #{ret}" if ret != 0
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def float_array(arr)
|
|
48
|
+
# SCS float = double
|
|
49
|
+
Fiddle::Pointer[arr.to_a.pack("d*")]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def read_float_array(ptr, size)
|
|
53
|
+
# SCS float = double
|
|
54
|
+
ptr[0, size * Fiddle::SIZEOF_DOUBLE].unpack("d*")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def int_array(arr)
|
|
58
|
+
# SCS int = int
|
|
59
|
+
Fiddle::Pointer[arr.to_a.pack("i!*")]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def read_string(char_ptr)
|
|
63
|
+
idx = char_ptr.index { |v| v == 0 }
|
|
64
|
+
char_ptr[0, idx].map(&:chr).join
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# TODO add support sparse matrices
|
|
68
|
+
def csc_matrix(mtx, upper: false)
|
|
69
|
+
mtx = mtx.to_a
|
|
70
|
+
|
|
71
|
+
m, n = shape(mtx)
|
|
72
|
+
|
|
73
|
+
cx = []
|
|
74
|
+
ci = []
|
|
75
|
+
cp = []
|
|
76
|
+
|
|
77
|
+
# CSC format
|
|
78
|
+
# https://www.gormanalysis.com/blog/sparse-matrix-storage-formats/
|
|
79
|
+
cp << 0
|
|
80
|
+
n.times do |j|
|
|
81
|
+
mtx.each_with_index do |row, i|
|
|
82
|
+
if row[j] != 0 && (!upper || i <= j)
|
|
83
|
+
cx << row[j]
|
|
84
|
+
ci << i
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
# cumulative column values
|
|
88
|
+
cp << cx.size
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# construct matrix
|
|
92
|
+
matrix = ffi::Matrix.malloc
|
|
93
|
+
matrix.x = float_array(cx)
|
|
94
|
+
matrix.i = int_array(ci)
|
|
95
|
+
matrix.p = int_array(cp)
|
|
96
|
+
matrix.m = m
|
|
97
|
+
matrix.n = n
|
|
98
|
+
matrix
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def shape(a)
|
|
102
|
+
if defined?(Matrix) && a.is_a?(Matrix)
|
|
103
|
+
[a.row_count, a.column_count]
|
|
104
|
+
elsif defined?(Numo::NArray) && a.is_a?(Numo::NArray)
|
|
105
|
+
a.shape
|
|
106
|
+
else
|
|
107
|
+
[a.size, a.first.size]
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def create_data(data)
|
|
112
|
+
m, n = shape(data[:a])
|
|
113
|
+
cdata = ffi::Data.malloc
|
|
114
|
+
cdata.m = m
|
|
115
|
+
cdata.n = n
|
|
116
|
+
cdata.a = csc_matrix(data[:a])
|
|
117
|
+
cdata.b = float_array(data[:b])
|
|
118
|
+
cdata.c = float_array(data[:c])
|
|
119
|
+
cdata
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def create_cone(cone)
|
|
123
|
+
ccone = ffi::Cone.malloc
|
|
124
|
+
ccone.f = cone[:f].to_i
|
|
125
|
+
ccone.l = cone[:l].to_i
|
|
126
|
+
ccone.q = int_array(cone[:q])
|
|
127
|
+
ccone.qsize = cone[:q].to_a.size
|
|
128
|
+
ccone.s = int_array(cone[:s])
|
|
129
|
+
ccone.ssize = cone[:s].to_a.size
|
|
130
|
+
ccone.ep = cone[:ep].to_i
|
|
131
|
+
ccone.ed = cone[:ed].to_i
|
|
132
|
+
ccone.p = float_array(cone[:p])
|
|
133
|
+
ccone.psize = cone[:p].to_a.size
|
|
134
|
+
ccone
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def set_settings(data, settings)
|
|
138
|
+
set = ffi::Settings.malloc
|
|
139
|
+
data.stgs = set
|
|
140
|
+
ffi.scs_set_default_settings(data)
|
|
141
|
+
|
|
142
|
+
# hack for setting members with []=
|
|
143
|
+
# safer than send("#{k}=", v)
|
|
144
|
+
entity = set.to_ptr
|
|
145
|
+
settings.each do |k, v|
|
|
146
|
+
entity[k.to_s] = settings_value(v)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
set
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# handle booleans
|
|
153
|
+
def settings_value(v)
|
|
154
|
+
case v
|
|
155
|
+
when true
|
|
156
|
+
1
|
|
157
|
+
when false
|
|
158
|
+
0
|
|
159
|
+
else
|
|
160
|
+
v
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# alloc clear memory
|
|
165
|
+
def calloc(size)
|
|
166
|
+
Fiddle::Pointer["\x00" * size]
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def ffi
|
|
170
|
+
@ffi
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|