highs 0.1.0
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 +3 -0
- data/LICENSE.txt +25 -0
- data/README.md +96 -0
- data/lib/highs/array.rb +37 -0
- data/lib/highs/ffi.rb +40 -0
- data/lib/highs/methods.rb +125 -0
- data/lib/highs/version.rb +3 -0
- data/lib/highs.rb +39 -0
- data/vendor/LICENSE +24 -0
- data/vendor/libhighs.arm64.dylib +0 -0
- data/vendor/libhighs.arm64.so +0 -0
- data/vendor/libhighs.dylib +0 -0
- data/vendor/libhighs.so +0 -0
- metadata +55 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 39ebf3fc768ecb688ec539a334c754f573c5f3f070b184f16a946602f12ad3ab
|
4
|
+
data.tar.gz: 856643d58ea6598e0770fdf43d31f1edd01b5715d695774617d933b08ac25182
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 75b9b9df7e57ac0a0cd64368bbe68377b6968eb095762c3cd5b645836e162488b38021fe1cb6bd4099f4f41433d6006f67c4bfc847d979f69cb233f494a4ab30
|
7
|
+
data.tar.gz: 6efca39cba247de891c5aed30e4d9ca6dc1a0a5c1190b357271d96cf16cbaf8d44873fcd4a8a1c1886245c9cdfea8081bf1a372c3ab32f10a68e000b901fc42f
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2021 ERGO-Code
|
4
|
+
Copyright (c) 2022 Andrew Kane
|
5
|
+
|
6
|
+
IPX and BASICLU, Copyright (c) 2018-2021 ERGO-Code
|
7
|
+
Used in HiGHS under the MIT license.
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
11
|
+
in the Software without restriction, including without limitation the rights
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
14
|
+
furnished to do so, subject to the following conditions:
|
15
|
+
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
17
|
+
copies or substantial portions of the Software.
|
18
|
+
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
25
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# HiGHS Ruby
|
2
|
+
|
3
|
+
[HiGHS](https://www.maths.ed.ac.uk/hall/HiGHS/) - linear optimization software - for Ruby
|
4
|
+
|
5
|
+
[](https://github.com/ankane/highs-ruby/actions)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application’s Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem "highs"
|
13
|
+
```
|
14
|
+
|
15
|
+
## Getting Started
|
16
|
+
|
17
|
+
*The API is fairly low-level at the moment*
|
18
|
+
|
19
|
+
Solve a linear program
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
Highs.lp_call(
|
23
|
+
sense: :minimize,
|
24
|
+
col_cost: [8, 10],
|
25
|
+
col_lower: [0, 0],
|
26
|
+
col_upper: [1e30, 1e30],
|
27
|
+
row_lower: [7, 12, 6],
|
28
|
+
row_upper: [1e30, 1e30, 1e30],
|
29
|
+
a_format: :colwise,
|
30
|
+
a_start: [0, 3],
|
31
|
+
a_index: [0, 1, 2, 0, 1, 2],
|
32
|
+
a_value: [2, 3, 2, 2, 4, 1]
|
33
|
+
)
|
34
|
+
```
|
35
|
+
|
36
|
+
Solve a mixed-integer program
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
Highs.mip_call(
|
40
|
+
sense: :minimize,
|
41
|
+
col_cost: [8, 10],
|
42
|
+
col_lower: [0, 0],
|
43
|
+
col_upper: [1e30, 1e30],
|
44
|
+
row_lower: [7, 12, 6],
|
45
|
+
row_upper: [1e30, 1e30, 1e30],
|
46
|
+
a_format: :colwise,
|
47
|
+
a_start: [0, 3],
|
48
|
+
a_index: [0, 1, 2, 0, 1, 2],
|
49
|
+
a_value: [2, 3, 2, 2, 4, 1],
|
50
|
+
integrality: [1, 1]
|
51
|
+
)
|
52
|
+
```
|
53
|
+
|
54
|
+
Solve a quadratic program
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
Highs.qp_call(
|
58
|
+
sense: :minimize,
|
59
|
+
col_cost: [0, -1, 0],
|
60
|
+
col_lower: [0, 0, 0],
|
61
|
+
col_upper: [1e30, 1e30, 1e30],
|
62
|
+
row_lower: [1, -1e30],
|
63
|
+
row_upper: [1e30, 1e30],
|
64
|
+
a_format: :colwise,
|
65
|
+
a_start: [0, 1, 2],
|
66
|
+
a_index: [0, 0, 0],
|
67
|
+
a_value: [1, 1, 1],
|
68
|
+
q_format: :colwise,
|
69
|
+
q_start: [0, 2, 3],
|
70
|
+
q_index: [0, 2, 1, 0, 2],
|
71
|
+
q_value: [2, -1, 0.2, -1, 2]
|
72
|
+
)
|
73
|
+
```
|
74
|
+
|
75
|
+
## History
|
76
|
+
|
77
|
+
View the [changelog](https://github.com/ankane/highs-ruby/blob/master/CHANGELOG.md)
|
78
|
+
|
79
|
+
## Contributing
|
80
|
+
|
81
|
+
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
82
|
+
|
83
|
+
- [Report bugs](https://github.com/ankane/highs-ruby/issues)
|
84
|
+
- Fix bugs and [submit pull requests](https://github.com/ankane/highs-ruby/pulls)
|
85
|
+
- Write, clarify, or fix documentation
|
86
|
+
- Suggest or add new features
|
87
|
+
|
88
|
+
To get started with development:
|
89
|
+
|
90
|
+
```sh
|
91
|
+
git clone https://github.com/ankane/highs-ruby.git
|
92
|
+
cd highs-ruby
|
93
|
+
bundle install
|
94
|
+
bundle exec rake vendor:all
|
95
|
+
bundle exec rake test
|
96
|
+
```
|
data/lib/highs/array.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Highs
|
2
|
+
class BaseArray
|
3
|
+
NOT_SET = Object.new
|
4
|
+
|
5
|
+
def initialize(size, value = NOT_SET)
|
6
|
+
@size = size
|
7
|
+
@ptr =
|
8
|
+
if value == NOT_SET
|
9
|
+
Fiddle::Pointer.malloc(size * self.class::SIZE)
|
10
|
+
else
|
11
|
+
if value.size != size
|
12
|
+
# TODO add variable name to message
|
13
|
+
raise ArgumentError, "wrong size (given #{value.size}, expected #{size})"
|
14
|
+
end
|
15
|
+
Fiddle::Pointer[value.pack("#{self.class::FORMAT}#{size}")]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_a
|
20
|
+
@ptr[0, @size * self.class::SIZE].unpack("#{self.class::FORMAT}#{@size}")
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_ptr
|
24
|
+
@ptr
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class DoubleArray < BaseArray
|
29
|
+
FORMAT = "d"
|
30
|
+
SIZE = Fiddle::SIZEOF_DOUBLE
|
31
|
+
end
|
32
|
+
|
33
|
+
class IntArray < BaseArray
|
34
|
+
FORMAT = "i!"
|
35
|
+
SIZE = Fiddle::SIZEOF_INT
|
36
|
+
end
|
37
|
+
end
|
data/lib/highs/ffi.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Highs
|
2
|
+
module FFI
|
3
|
+
extend Fiddle::Importer
|
4
|
+
|
5
|
+
libs = Array(Highs.ffi_lib).dup
|
6
|
+
begin
|
7
|
+
dlload Fiddle.dlopen(libs.shift)
|
8
|
+
rescue Fiddle::DLError => e
|
9
|
+
retry if libs.any?
|
10
|
+
raise e
|
11
|
+
end
|
12
|
+
|
13
|
+
# https://github.com/ERGO-Code/HiGHS/blob/master/src/interfaces/highs_c_api.h
|
14
|
+
|
15
|
+
MODEL_STATUS = [
|
16
|
+
:not_set, :load_error, :model_error, :presolve_error, :solve_error, :postsolve_error,
|
17
|
+
:model_empty, :optimal, :infeasible, :unbounded_or_infeasible, :unbounded,
|
18
|
+
:objective_bound, :objective_target, :time_limit, :iteration_limit, :unknown
|
19
|
+
]
|
20
|
+
|
21
|
+
MATRIX_FORMAT = {
|
22
|
+
colwise: 1,
|
23
|
+
rowwise: 2
|
24
|
+
}
|
25
|
+
|
26
|
+
OBJ_SENSE = {
|
27
|
+
minimize: 1,
|
28
|
+
maximize: -1
|
29
|
+
}
|
30
|
+
|
31
|
+
BASIS_STATUS = [:lower, :basic, :upper, :zero, :nonbasic]
|
32
|
+
|
33
|
+
typealias "HighsInt", "int"
|
34
|
+
typealias "HighsUInt", "unsigned int"
|
35
|
+
|
36
|
+
extern "HighsInt Highs_lpCall(HighsInt num_col, HighsInt num_row, HighsInt num_nz, HighsInt a_format, HighsInt sense, double offset, double* col_cost, double* col_lower, double* col_upper, double* row_lower, double* row_upper, HighsInt* a_start, HighsInt* a_index, double* a_value, double* col_value, double* col_dual, double* row_value, double* row_dual, HighsInt* col_basis_status, HighsInt* row_basis_status, HighsInt* model_status)"
|
37
|
+
extern "HighsInt Highs_mipCall(HighsInt num_col, HighsInt num_row, HighsInt num_nz, HighsInt a_format, HighsInt sense, double offset, double* col_cost, double* col_lower, double* col_upper, double* row_lower, double* row_upper, HighsInt* a_start, HighsInt* a_index, double* a_value, HighsInt* integrality, double* col_value, double* row_value, HighsInt* model_status)"
|
38
|
+
extern "HighsInt Highs_qpCall(HighsInt num_col, HighsInt num_row, HighsInt num_nz, HighsInt q_num_nz, HighsInt a_format, HighsInt q_format, HighsInt sense, double offset, double* col_cost, double* col_lower, double* col_upper, double* row_lower, double* row_upper, HighsInt* a_start, HighsInt* a_index, double* a_value, HighsInt* q_start, HighsInt* q_index, double* q_value, double* col_value, double* col_dual, double* row_value, double* row_dual, HighsInt* col_basis_status, HighsInt* row_basis_status, HighsInt* model_status)"
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Highs
|
2
|
+
module Methods
|
3
|
+
def lp_call(sense:, offset: 0, col_cost:, col_lower:, col_upper:, row_lower:, row_upper:, a_format:, a_start:, a_index:, a_value:)
|
4
|
+
num_col = col_cost.size
|
5
|
+
num_row = row_lower.size
|
6
|
+
num_nz = a_index.size
|
7
|
+
a_format = FFI::MATRIX_FORMAT.fetch(a_format)
|
8
|
+
sense = FFI::OBJ_SENSE.fetch(sense)
|
9
|
+
|
10
|
+
a_start_size = a_start.size
|
11
|
+
|
12
|
+
col_value = DoubleArray.new(num_col)
|
13
|
+
col_dual = DoubleArray.new(num_col)
|
14
|
+
row_value = DoubleArray.new(num_row)
|
15
|
+
row_dual = DoubleArray.new(num_row)
|
16
|
+
col_basis = IntArray.new(num_col)
|
17
|
+
row_basis = IntArray.new(num_row)
|
18
|
+
model_status = IntArray.new(1)
|
19
|
+
|
20
|
+
check_status FFI.Highs_lpCall(
|
21
|
+
num_col, num_row, num_nz, a_format, sense, offset,
|
22
|
+
DoubleArray.new(num_col, col_cost), DoubleArray.new(num_col, col_lower), DoubleArray.new(num_col, col_upper),
|
23
|
+
DoubleArray.new(num_row, row_lower), DoubleArray.new(num_row, row_upper),
|
24
|
+
IntArray.new(a_start_size, a_start), IntArray.new(num_nz, a_index), DoubleArray.new(num_nz, a_value),
|
25
|
+
col_value, col_dual,
|
26
|
+
row_value, row_dual,
|
27
|
+
col_basis, row_basis,
|
28
|
+
model_status
|
29
|
+
)
|
30
|
+
|
31
|
+
{
|
32
|
+
status: FFI::MODEL_STATUS[model_status.to_a.first],
|
33
|
+
col_value: col_value.to_a,
|
34
|
+
col_dual: col_dual.to_a,
|
35
|
+
row_value: row_value.to_a,
|
36
|
+
row_dual: row_dual.to_a,
|
37
|
+
col_basis: col_basis.to_a.map { |v| FFI::BASIS_STATUS[v] },
|
38
|
+
row_basis: row_basis.to_a.map { |v| FFI::BASIS_STATUS[v] }
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def mip_call(sense:, offset: 0, col_cost:, col_lower:, col_upper:, row_lower:, row_upper:, a_format:, a_start:, a_index:, a_value:, integrality:)
|
43
|
+
num_col = col_cost.size
|
44
|
+
num_row = row_lower.size
|
45
|
+
num_nz = a_index.size
|
46
|
+
a_format = FFI::MATRIX_FORMAT.fetch(a_format)
|
47
|
+
sense = FFI::OBJ_SENSE.fetch(sense)
|
48
|
+
|
49
|
+
a_start_size = a_start.size
|
50
|
+
|
51
|
+
col_value = DoubleArray.new(num_col)
|
52
|
+
row_value = DoubleArray.new(num_row)
|
53
|
+
model_status = IntArray.new(1)
|
54
|
+
|
55
|
+
check_status FFI.Highs_mipCall(
|
56
|
+
num_col, num_row, num_nz, a_format, sense, offset,
|
57
|
+
DoubleArray.new(num_col, col_cost), DoubleArray.new(num_col, col_lower), DoubleArray.new(num_col, col_upper),
|
58
|
+
DoubleArray.new(num_row, row_lower), DoubleArray.new(num_row, row_upper),
|
59
|
+
IntArray.new(a_start_size, a_start), IntArray.new(num_nz, a_index), DoubleArray.new(num_nz, a_value),
|
60
|
+
IntArray.new(num_col, integrality),
|
61
|
+
col_value,
|
62
|
+
row_value,
|
63
|
+
model_status
|
64
|
+
)
|
65
|
+
|
66
|
+
{
|
67
|
+
status: FFI::MODEL_STATUS[model_status.to_a.first],
|
68
|
+
col_value: col_value.to_a,
|
69
|
+
row_value: row_value.to_a
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def qp_call(sense:, offset: 0, col_cost:, col_lower:, col_upper:, row_lower:, row_upper:, a_format:, a_start:, a_index:, a_value:, q_format:, q_start:, q_index:, q_value:)
|
74
|
+
num_col = col_cost.size
|
75
|
+
num_row = row_lower.size
|
76
|
+
num_nz = a_index.size
|
77
|
+
q_num_nz = q_index.size
|
78
|
+
a_format = FFI::MATRIX_FORMAT.fetch(a_format)
|
79
|
+
q_format = FFI::MATRIX_FORMAT.fetch(q_format)
|
80
|
+
sense = FFI::OBJ_SENSE.fetch(sense)
|
81
|
+
|
82
|
+
a_start_size = a_start.size
|
83
|
+
q_start_size = q_start.size
|
84
|
+
|
85
|
+
col_value = DoubleArray.new(num_col)
|
86
|
+
col_dual = DoubleArray.new(num_col)
|
87
|
+
row_value = DoubleArray.new(num_row)
|
88
|
+
row_dual = DoubleArray.new(num_row)
|
89
|
+
col_basis = IntArray.new(num_col)
|
90
|
+
row_basis = IntArray.new(num_row)
|
91
|
+
model_status = IntArray.new(1)
|
92
|
+
|
93
|
+
check_status FFI.Highs_qpCall(
|
94
|
+
num_col, num_row, num_nz, q_num_nz, a_format, q_format, sense, offset,
|
95
|
+
DoubleArray.new(num_col, col_cost), DoubleArray.new(num_col, col_lower), DoubleArray.new(num_col, col_upper),
|
96
|
+
DoubleArray.new(num_row, row_lower), DoubleArray.new(num_row, row_upper),
|
97
|
+
IntArray.new(a_start_size, a_start), IntArray.new(num_nz, a_index), DoubleArray.new(num_nz, a_value),
|
98
|
+
IntArray.new(q_start_size, q_start), IntArray.new(q_num_nz, q_index), DoubleArray.new(q_num_nz, q_value),
|
99
|
+
col_value, col_dual,
|
100
|
+
row_value, row_dual,
|
101
|
+
col_basis, row_basis,
|
102
|
+
model_status
|
103
|
+
)
|
104
|
+
|
105
|
+
{
|
106
|
+
status: FFI::MODEL_STATUS[model_status.to_a.first],
|
107
|
+
col_value: col_value.to_a,
|
108
|
+
col_dual: col_dual.to_a,
|
109
|
+
row_value: row_value.to_a,
|
110
|
+
row_dual: row_dual.to_a,
|
111
|
+
col_basis: col_basis.to_a.map { |v| FFI::BASIS_STATUS[v] },
|
112
|
+
row_basis: row_basis.to_a.map { |v| FFI::BASIS_STATUS[v] }
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def check_status(status)
|
119
|
+
# TODO handle warnings (status = 1)
|
120
|
+
if status == -1
|
121
|
+
raise Error, "Bad status"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/highs.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# stdlib
|
2
|
+
require "fiddle/import"
|
3
|
+
|
4
|
+
# modules
|
5
|
+
require "highs/array"
|
6
|
+
require "highs/methods"
|
7
|
+
require "highs/version"
|
8
|
+
|
9
|
+
module Highs
|
10
|
+
class Error < StandardError; end
|
11
|
+
|
12
|
+
extend Methods
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_accessor :ffi_lib
|
16
|
+
end
|
17
|
+
lib_name =
|
18
|
+
if Gem.win_platform?
|
19
|
+
# uses lib prefix for Windows
|
20
|
+
"libhighs.dll"
|
21
|
+
elsif RbConfig::CONFIG["host_os"] =~ /darwin/i
|
22
|
+
if RbConfig::CONFIG["host_cpu"] =~ /arm|aarch64/i
|
23
|
+
"libhighs.arm64.dylib"
|
24
|
+
else
|
25
|
+
"libhighs.dylib"
|
26
|
+
end
|
27
|
+
else
|
28
|
+
if RbConfig::CONFIG["host_cpu"] =~ /arm|aarch64/i
|
29
|
+
"libhighs.arm64.so"
|
30
|
+
else
|
31
|
+
"libhighs.so"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
vendor_lib = File.expand_path("../vendor/#{lib_name}", __dir__)
|
35
|
+
self.ffi_lib = [vendor_lib]
|
36
|
+
|
37
|
+
# friendlier error message
|
38
|
+
autoload :FFI, "highs/ffi"
|
39
|
+
end
|
data/vendor/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2021 ERGO-Code
|
4
|
+
|
5
|
+
IPX and BASICLU, Copyright (c) 2018-2021 ERGO-Code
|
6
|
+
Used in HiGHS under the MIT license.
|
7
|
+
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
+
of this software and associated documentation files (the "Software"), to deal
|
10
|
+
in the Software without restriction, including without limitation the rights
|
11
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
+
copies of the Software, and to permit persons to whom the Software is
|
13
|
+
furnished to do so, subject to the following conditions:
|
14
|
+
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
16
|
+
copies or substantial portions of the Software.
|
17
|
+
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
24
|
+
SOFTWARE.
|
Binary file
|
Binary file
|
Binary file
|
data/vendor/libhighs.so
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: highs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Kane
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-04-05 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email: andrew@ankane.org
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- CHANGELOG.md
|
20
|
+
- LICENSE.txt
|
21
|
+
- README.md
|
22
|
+
- lib/highs.rb
|
23
|
+
- lib/highs/array.rb
|
24
|
+
- lib/highs/ffi.rb
|
25
|
+
- lib/highs/methods.rb
|
26
|
+
- lib/highs/version.rb
|
27
|
+
- vendor/LICENSE
|
28
|
+
- vendor/libhighs.arm64.dylib
|
29
|
+
- vendor/libhighs.arm64.so
|
30
|
+
- vendor/libhighs.dylib
|
31
|
+
- vendor/libhighs.so
|
32
|
+
homepage: https://github.com/ankane/highs-ruby
|
33
|
+
licenses:
|
34
|
+
- MIT
|
35
|
+
metadata: {}
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '2.7'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubygems_version: 3.1.6
|
52
|
+
signing_key:
|
53
|
+
specification_version: 4
|
54
|
+
summary: Linear optimization for Ruby
|
55
|
+
test_files: []
|