ruby-cbc 0.3.18 → 0.3.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -1
- data/.rubocop_todo.yml +51 -0
- data/.ruby-style.yml +6 -1346
- data/.travis.yml +3 -1
- data/Gemfile +1 -1
- data/README.md +53 -10
- data/Rakefile +6 -6
- data/lib/ruby-cbc/conflict_solver.rb +9 -8
- data/lib/ruby-cbc/ilp/constraint.rb +1 -1
- data/lib/ruby-cbc/ilp/term_array.rb +2 -2
- data/lib/ruby-cbc/model.rb +9 -9
- data/lib/ruby-cbc/problem.rb +26 -26
- data/lib/ruby-cbc/version.rb +1 -1
- data/lib/ruby-cbc.rb +2 -2
- data/ruby-cbc.gemspec +10 -9
- metadata +43 -15
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
[![Build Status](https://travis-ci.org/gverger/ruby-cbc.svg?branch=master)](https://travis-ci.org/gverger/ruby-cbc)
|
2
|
+
|
2
3
|
# Ruby-Cbc
|
3
4
|
|
4
5
|
This gem is using Cbc, an Integer Linear Programming Library, to provide optimization problems solving
|
@@ -8,6 +9,13 @@ It uses the version 2.9.9 of Cbc, and requires the version 2.9.9 of gem cbc-wrap
|
|
8
9
|
|
9
10
|
## Installation
|
10
11
|
|
12
|
+
You need to have `cbc` installed for `ruby-cbc` to work.
|
13
|
+
|
14
|
+
- On a mac, you can execute `brew install cbc`
|
15
|
+
- On Debian and Ubuntu, use `apt-get install coinor-libcbc-dev`
|
16
|
+
- On Archlinux, use `pacman -S coin-or-cbc`
|
17
|
+
- On docker you can check the dockerfiles in test/installation-tests/
|
18
|
+
|
11
19
|
Add this line to your application's Gemfile:
|
12
20
|
|
13
21
|
```ruby
|
@@ -22,16 +30,25 @@ Or install it yourself as:
|
|
22
30
|
|
23
31
|
$ gem install ruby-cbc
|
24
32
|
|
25
|
-
|
26
|
-
|
27
|
-
|
33
|
+
### Heroku
|
34
|
+
|
35
|
+
On Heroku, you will need to tweak your installation a bit: you can install the cbc library with
|
36
|
+
the [Apt](https://github.com/heroku/heroku-buildpack-apt) buildpack with an Aptfile of:
|
37
|
+
|
38
|
+
```
|
39
|
+
coinor-libcbc-dev
|
40
|
+
```
|
41
|
+
|
42
|
+
You will need to set LD_LIBRARY_PATH so it can find LAPACK and BLAS (see this [issue](https://github.com/heroku/heroku-buildpack-apt/issues/35)).
|
28
43
|
|
29
|
-
|
44
|
+
```
|
45
|
+
heroku config:set LD_LIBRARY_PATH=/app/.apt/usr/lib/x86_64-linux-gnu/lapack:/app/.apt/usr/lib/x86_64-linux-gnu/blas
|
46
|
+
```
|
30
47
|
|
31
48
|
## Usage
|
32
49
|
|
33
50
|
```ruby
|
34
|
-
# The same Brief Example as found in section 1.3 of
|
51
|
+
# The same Brief Example as found in section 1.3 of
|
35
52
|
# glpk-4.44/doc/glpk.pdf.
|
36
53
|
#
|
37
54
|
# maximize
|
@@ -52,39 +69,45 @@ m.maximize(10 * x1 + 6 * x2 + 4 * x3)
|
|
52
69
|
|
53
70
|
m.enforce(x1 + x2 + x3 <= 100)
|
54
71
|
m.enforce(10 * x1 + 4 * x2 + 5 * x3 <= 600)
|
55
|
-
m.enforce(2 * x1 + 2 * x2 + 6* x3 <= 300)
|
72
|
+
m.enforce(2 * x1 + 2 * x2 + 6 * x3 <= 300)
|
56
73
|
|
57
74
|
p = m.to_problem
|
58
75
|
|
59
76
|
p.solve
|
60
77
|
|
61
|
-
|
78
|
+
unless p.proven_infeasible?
|
62
79
|
puts "x1 = #{p.value_of(x1)}"
|
63
80
|
puts "x2 = #{p.value_of(x2)}"
|
64
81
|
puts "x3 = #{p.value_of(x3)}"
|
65
82
|
end
|
66
83
|
```
|
84
|
+
|
67
85
|
### Modelling
|
68
86
|
|
69
87
|
Let's have a model :
|
88
|
+
|
70
89
|
```ruby
|
71
90
|
model = Cbc::Model.new
|
72
91
|
```
|
92
|
+
|
73
93
|
#### The variables
|
74
94
|
|
75
95
|
3 variable kinds are available:
|
96
|
+
|
76
97
|
```ruby
|
77
98
|
x = model.bin_var(name: "x") # a binary variable (i.e. can take values 0 and 1)
|
78
99
|
y = model.int_var(L..U, name: "y") # a integer variable, L <= y <= U
|
79
100
|
z = model.cont_var(L..U, name: "z") # a continuous variable, L <= z <= U
|
80
101
|
```
|
102
|
+
|
81
103
|
Name is optional and used only when displaying the model.
|
82
104
|
|
83
105
|
If you don't specify the range, the variables are free.
|
84
|
-
You can also use
|
106
|
+
You can also use `Cbc::INF` as the infinity bound.
|
85
107
|
|
86
108
|
Each one of these 3 kinds have also an array method that generate several variables.
|
87
109
|
For instance to generate 3 positive integer variables named x, y and z :
|
110
|
+
|
88
111
|
```ruby
|
89
112
|
x, y, z = model.int_var_array(3, 0..Cbc::INF, names: ["x", "y", "z"])
|
90
113
|
```
|
@@ -92,12 +115,15 @@ x, y, z = model.int_var_array(3, 0..Cbc::INF, names: ["x", "y", "z"])
|
|
92
115
|
#### The constraints
|
93
116
|
|
94
117
|
You can enforce constraints:
|
118
|
+
|
95
119
|
```ruby
|
96
120
|
model.enforce(x + y - z <= 10)
|
97
121
|
```
|
122
|
+
|
98
123
|
You are not restricted to usual linear programming rules when writing a constraint.
|
99
|
-
Usually you would have to write
|
124
|
+
Usually you would have to write `x - y = 0` to express `x = y`.
|
100
125
|
Ruby-Cbc allows you to put variables and constants on both sides of the comparison operator. You can write
|
126
|
+
|
101
127
|
```ruby
|
102
128
|
model.enforce(x - y == 0)
|
103
129
|
model.enforce(x == y)
|
@@ -107,12 +133,14 @@ model.enforce(0 == x - y)
|
|
107
133
|
|
108
134
|
Ruby-Cbc allows you to name your constraints. Beware that their name is not an unique id. It is only a helper
|
109
135
|
for human readability, and several constraints can share the same function name.
|
136
|
+
|
110
137
|
```ruby
|
111
138
|
model.enforce(my_function_name: x + y <= 50)
|
112
139
|
model.constraints.map(&:to_function_s) # => ["my_function_name(x, y)"]
|
113
140
|
```
|
114
141
|
|
115
142
|
Linear constraints are usually of the form
|
143
|
+
|
116
144
|
```ruby
|
117
145
|
a1 * x1 + a2 * x2 + ... + an * xn <= C
|
118
146
|
a1 * x1 + a2 * x2 + ... + an * xn >= C
|
@@ -120,14 +148,17 @@ a1 * x1 + a2 * x2 + ... + an * xn == C
|
|
120
148
|
```
|
121
149
|
|
122
150
|
With Ruby-Cbc you can write
|
151
|
+
|
123
152
|
```ruby
|
124
153
|
2 * (2 + 5 * x) + 4 * 5 + 1 == 1 + 4 * 5 * y
|
125
154
|
```
|
155
|
+
|
126
156
|
The (in)equation must still be a **linear** (in)equation, you cannot multiply two variables !
|
127
157
|
|
128
158
|
#### Objective
|
129
159
|
|
130
160
|
You can set the objective:
|
161
|
+
|
131
162
|
```ruby
|
132
163
|
model.maximize(3 * x + 2 * y)
|
133
164
|
model.minimize(3 * x + 2 * y)
|
@@ -136,12 +167,15 @@ model.minimize(3 * x + 2 * y)
|
|
136
167
|
#### Displaying the model
|
137
168
|
|
138
169
|
the `Model` instances have a `to_s` method. You can then run
|
170
|
+
|
139
171
|
```ruby
|
140
172
|
puts model
|
141
173
|
```
|
174
|
+
|
142
175
|
The model will be printed in LP format.
|
143
176
|
|
144
177
|
For instance:
|
178
|
+
|
145
179
|
```
|
146
180
|
Maximize
|
147
181
|
+ 10 x1 + 6 x2 + 4 x3
|
@@ -167,25 +201,30 @@ End
|
|
167
201
|
### Solving
|
168
202
|
|
169
203
|
To solve the model, you need to first transform it to a problem.
|
204
|
+
|
170
205
|
```ruby
|
171
206
|
problem = model.to_problem
|
172
207
|
```
|
173
208
|
|
174
209
|
You can define a time limit to the resolution
|
210
|
+
|
175
211
|
```ruby
|
176
212
|
problem.set_time_limit(nb_seconds)
|
177
213
|
```
|
178
214
|
|
179
215
|
You can solve the Linear Problem
|
216
|
+
|
180
217
|
```ruby
|
181
218
|
problem.solve
|
182
219
|
```
|
183
220
|
|
184
221
|
You can specify arguments that match the cbc command line
|
222
|
+
|
185
223
|
```ruby
|
186
224
|
problem.solve(sec: 60) # equivalent to $ cbc -sec 60
|
187
225
|
problem.solve(log: 1) # equivalent to $ cbc -log 1
|
188
226
|
```
|
227
|
+
|
189
228
|
For more examples of available options, if `coinor-cbc` is installed run
|
190
229
|
|
191
230
|
$ cbc
|
@@ -193,6 +232,7 @@ For more examples of available options, if `coinor-cbc` is installed run
|
|
193
232
|
then type `?`
|
194
233
|
|
195
234
|
Once `problem.solve` has finished you can query the status:
|
235
|
+
|
196
236
|
```ruby
|
197
237
|
problem.proven_infeasible? # will tell you if the problem has no solution
|
198
238
|
problem.proven_optimal? # will tell you if the problem is solved optimally
|
@@ -200,6 +240,7 @@ problem.time_limit_reached? # Will tell you if the solve timed out
|
|
200
240
|
```
|
201
241
|
|
202
242
|
To have the different values, do
|
243
|
+
|
203
244
|
```ruby
|
204
245
|
problem.objective_value # Will tell you the value of the best objective
|
205
246
|
problem.best_bound # Will tell you the best known bound
|
@@ -211,16 +252,19 @@ problem.value_of(var) # will tell you the computed value or a variable
|
|
211
252
|
|
212
253
|
Sometimes a problem has no feasible solution. In this case, one may wonder what is the minimum subset of conflicting
|
213
254
|
inequations. For this prupose, you can use
|
255
|
+
|
214
256
|
```ruby
|
215
257
|
problem.find_conflict # Will return an array of constraints that form an unsatifiable set
|
216
258
|
problem.find_conflict_vars # Will return all variables involved in the unsatisfiable minimum set of constraints
|
217
259
|
```
|
260
|
+
|
218
261
|
It finds a minimum subset of constraints that make the problem unsatisfiable. Note that there could be several of them,
|
219
262
|
but the solver only computes the first one it finds. Note also that it does so by solving several instances
|
220
263
|
of relaxed versions of the problem. It might take some time! It is based on QuickXplain
|
221
264
|
(http://dl.acm.org/citation.cfm?id=1597177).
|
222
265
|
|
223
266
|
One way to see the results nicely could be
|
267
|
+
|
224
268
|
```ruby
|
225
269
|
problem.find_conflict.map(&:to_function_s)
|
226
270
|
```
|
@@ -228,4 +272,3 @@ problem.find_conflict.map(&:to_function_s)
|
|
228
272
|
## Contributing
|
229
273
|
|
230
274
|
Bug reports and pull requests are welcome on GitHub at https://github.com/gverger/ruby-cbc.
|
231
|
-
|
data/Rakefile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rspec/core/rake_task"
|
3
|
-
require
|
3
|
+
require "rake/extensiontask"
|
4
4
|
|
5
5
|
def in_dir(path)
|
6
6
|
original_dir = Dir.pwd
|
@@ -12,14 +12,14 @@ end
|
|
12
12
|
|
13
13
|
RSpec::Core::RakeTask.new(:spec)
|
14
14
|
|
15
|
-
spec = Gem::Specification.load(
|
16
|
-
Rake::ExtensionTask.new(
|
17
|
-
ext.lib_dir =
|
15
|
+
spec = Gem::Specification.load("ruby-cbc.gemspec")
|
16
|
+
Rake::ExtensionTask.new("ruby-cbc", spec) do |ext|
|
17
|
+
ext.lib_dir = "lib/ruby-cbc"
|
18
18
|
ext.tmp_dir = "tmp"
|
19
|
-
ext.name =
|
19
|
+
ext.name = "cbc_wrapper"
|
20
20
|
end
|
21
21
|
|
22
|
-
task :
|
22
|
+
task default: [:spec]
|
23
23
|
|
24
24
|
task :benchmark do
|
25
25
|
ruby "test/benchmark.rb"
|
@@ -19,7 +19,8 @@ module Cbc
|
|
19
19
|
max_iter = 1
|
20
20
|
conflict_set_size = 0
|
21
21
|
loop do
|
22
|
-
range_idxs =
|
22
|
+
range_idxs =
|
23
|
+
first_failing(conflict_set_size, crs, continuous: continuous, max_iterations: max_iter)
|
23
24
|
break if range_idxs.nil?
|
24
25
|
crs = crs.restrict_to_n_constraints(range_idxs.max + 1)
|
25
26
|
crs.move_constraint_to_start(range_idxs)
|
@@ -43,7 +44,9 @@ module Cbc
|
|
43
44
|
nb_clusters_one_constraint += 1
|
44
45
|
end
|
45
46
|
if nb_clusters_one_constraint > 0
|
46
|
-
crs.move_constraint_to_start(
|
47
|
+
crs.move_constraint_to_start(
|
48
|
+
(crs.nb_constraints - nb_clusters_one_constraint)..(crs.nb_constraints - 1)
|
49
|
+
)
|
47
50
|
clusters[nb_clusters_one_constraint, clusters.size - nb_clusters_one_constraint] =
|
48
51
|
clusters[0, clusters.size - nb_clusters_one_constraint]
|
49
52
|
clusters[0, nb_clusters_one_constraint] = Array.new(nb_clusters_one_constraint, 1)
|
@@ -83,14 +86,12 @@ module Cbc
|
|
83
86
|
min_idx = half_constraint_idx + 1
|
84
87
|
# puts " FEAS"
|
85
88
|
end
|
86
|
-
if max_idx
|
87
|
-
|
88
|
-
|
89
|
-
return min_idx..max_idx
|
90
|
-
end
|
89
|
+
next if max_idx != min_idx
|
90
|
+
return nil if max_idx > crs.nb_constraints
|
91
|
+
return min_idx..max_idx
|
91
92
|
end
|
92
93
|
# Shouldn't come here if the whole problem is infeasible
|
93
|
-
|
94
|
+
nil
|
94
95
|
end
|
95
96
|
|
96
97
|
def infeasible?(problem)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "forwardable"
|
2
2
|
|
3
3
|
module Ilp
|
4
4
|
class TermArray
|
@@ -33,7 +33,7 @@ module Ilp
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def *(other)
|
36
|
-
raise ArgumentError,
|
36
|
+
raise ArgumentError, "Argument is not numeric" unless other.is_a? Numeric
|
37
37
|
new_terms = terms.map { |term| term * other }
|
38
38
|
TermArray.new(new_terms)
|
39
39
|
end
|
data/lib/ruby-cbc/model.rb
CHANGED
@@ -91,7 +91,7 @@ module Cbc
|
|
91
91
|
constraints.each do |cons|
|
92
92
|
str << " #{cons}\n"
|
93
93
|
end
|
94
|
-
bounded_vars = vars.
|
94
|
+
bounded_vars = vars.reject { |v| v.kind == Ilp::Var::BINARY_KIND }
|
95
95
|
unless bounded_vars.empty?
|
96
96
|
str << "\nBounds\n"
|
97
97
|
bounded_vars.each do |v|
|
@@ -133,16 +133,16 @@ module Cbc
|
|
133
133
|
v
|
134
134
|
end
|
135
135
|
|
136
|
-
def lb_to_s(
|
137
|
-
return "-inf" if
|
138
|
-
return "+inf" if
|
139
|
-
|
136
|
+
def lb_to_s(lower_bound)
|
137
|
+
return "-inf" if lower_bound.nil? || lower_bound == -Cbc::INF
|
138
|
+
return "+inf" if lower_bound == Cbc::INF
|
139
|
+
lower_bound.to_s
|
140
140
|
end
|
141
141
|
|
142
|
-
def ub_to_s(
|
143
|
-
return "+inf" if
|
144
|
-
return "-inf" if
|
145
|
-
|
142
|
+
def ub_to_s(upper_bound)
|
143
|
+
return "+inf" if upper_bound.nil? || upper_bound == Cbc::INF
|
144
|
+
return "-inf" if upper_bound == -Cbc::INF
|
145
|
+
upper_bound.to_s
|
146
146
|
end
|
147
147
|
end
|
148
148
|
end
|
data/lib/ruby-cbc/problem.rb
CHANGED
@@ -56,9 +56,6 @@ module Cbc
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def create_cbc_problem(continuous: false)
|
59
|
-
@int_arrays = []
|
60
|
-
@double_arrays = []
|
61
|
-
|
62
59
|
ccs = self.class.crs_to_ccs(@crs)
|
63
60
|
objective = Array.new(ccs.nb_vars, 0)
|
64
61
|
if model.objective
|
@@ -69,10 +66,18 @@ module Cbc
|
|
69
66
|
|
70
67
|
@cbc_model = Cbc_wrapper.Cbc_newModel
|
71
68
|
Cbc_wrapper.Cbc_loadProblem(
|
72
|
-
@cbc_model,
|
73
|
-
|
74
|
-
|
75
|
-
|
69
|
+
@cbc_model,
|
70
|
+
ccs.nb_vars,
|
71
|
+
@crs.nb_constraints,
|
72
|
+
to_int_array(ccs.col_ptr),
|
73
|
+
to_int_array(ccs.row_idx),
|
74
|
+
to_double_array(ccs.values),
|
75
|
+
nil,
|
76
|
+
nil,
|
77
|
+
to_double_array(objective),
|
78
|
+
nil,
|
79
|
+
nil
|
80
|
+
)
|
76
81
|
|
77
82
|
# Segmentation errors when setting name
|
78
83
|
# Cbc_wrapper.Cbc_setProblemName(@cbc_model, model.name) if model.name
|
@@ -106,22 +111,20 @@ module Cbc
|
|
106
111
|
idx += 1
|
107
112
|
end
|
108
113
|
|
109
|
-
ObjectSpace.define_finalizer(self, self.class.finalizer(@cbc_model
|
114
|
+
ObjectSpace.define_finalizer(self, self.class.finalizer(@cbc_model))
|
110
115
|
|
111
|
-
@default_solve_params = {
|
112
|
-
log: 0
|
113
|
-
}
|
116
|
+
@default_solve_params = { log: 0 }
|
114
117
|
end
|
115
118
|
|
116
|
-
def set_constraint_bounds(
|
117
|
-
case
|
119
|
+
def set_constraint_bounds(constraint, idx)
|
120
|
+
case constraint.type
|
118
121
|
when Ilp::Constraint::LESS_OR_EQ
|
119
|
-
Cbc_wrapper.Cbc_setRowUpper(@cbc_model, idx,
|
122
|
+
Cbc_wrapper.Cbc_setRowUpper(@cbc_model, idx, constraint.bound)
|
120
123
|
when Ilp::Constraint::GREATER_OR_EQ
|
121
|
-
Cbc_wrapper.Cbc_setRowLower(@cbc_model, idx,
|
124
|
+
Cbc_wrapper.Cbc_setRowLower(@cbc_model, idx, constraint.bound)
|
122
125
|
when Ilp::Constraint::EQUALS
|
123
|
-
Cbc_wrapper.Cbc_setRowUpper(@cbc_model, idx,
|
124
|
-
Cbc_wrapper.Cbc_setRowLower(@cbc_model, idx,
|
126
|
+
Cbc_wrapper.Cbc_setRowUpper(@cbc_model, idx, constraint.bound)
|
127
|
+
Cbc_wrapper.Cbc_setRowLower(@cbc_model, idx, constraint.bound)
|
125
128
|
end
|
126
129
|
end
|
127
130
|
|
@@ -131,8 +134,6 @@ module Cbc
|
|
131
134
|
end
|
132
135
|
Cbc_wrapper.Cbc_solve(@cbc_model)
|
133
136
|
@solution = Cbc_wrapper::DoubleArray.frompointer(Cbc_wrapper.Cbc_getColSolution(@cbc_model))
|
134
|
-
@double_arrays << @solution
|
135
|
-
@solution
|
136
137
|
end
|
137
138
|
|
138
139
|
def value_of(var)
|
@@ -145,9 +146,12 @@ module Cbc
|
|
145
146
|
end
|
146
147
|
end
|
147
148
|
|
149
|
+
# Keep this one for back compatibility
|
150
|
+
# rubocop:disable Naming/AccessorMethodName
|
148
151
|
def set_time_limit(seconds)
|
149
152
|
@default_solve_params[:sec] = seconds
|
150
153
|
end
|
154
|
+
# rubocop:enable Naming/AccessorMethodName
|
151
155
|
|
152
156
|
def proven_optimal?
|
153
157
|
Cbc_wrapper.Cbc_isProvenOptimal(@cbc_model) == 1
|
@@ -175,18 +179,16 @@ module Cbc
|
|
175
179
|
end
|
176
180
|
|
177
181
|
def find_conflict
|
178
|
-
@
|
182
|
+
@find_conflict ||= ConflictSolver.new(self).find_conflict
|
179
183
|
end
|
180
184
|
|
181
185
|
def find_conflict_vars
|
182
|
-
@
|
186
|
+
@find_conflict_vars ||= find_conflict.map(&:vars).flatten.uniq
|
183
187
|
end
|
184
188
|
|
185
|
-
def self.finalizer(cbc_model
|
189
|
+
def self.finalizer(cbc_model)
|
186
190
|
proc do
|
187
191
|
Cbc_wrapper.Cbc_deleteModel(cbc_model)
|
188
|
-
int_arrays.each { |ar| Cbc_wrapper.delete_intArray(ar) }
|
189
|
-
double_arrays.each { |ar| Cbc_wrapper.delete_doubleArray(ar) }
|
190
192
|
end
|
191
193
|
end
|
192
194
|
|
@@ -203,7 +205,6 @@ module Cbc
|
|
203
205
|
c_array[idx] = array[idx]
|
204
206
|
idx += 1
|
205
207
|
end
|
206
|
-
@int_arrays << c_array
|
207
208
|
c_array
|
208
209
|
end
|
209
210
|
|
@@ -214,7 +215,6 @@ module Cbc
|
|
214
215
|
c_array[idx] = array[idx]
|
215
216
|
idx += 1
|
216
217
|
end
|
217
|
-
@double_arrays << c_array
|
218
218
|
c_array
|
219
219
|
end
|
220
220
|
end
|
data/lib/ruby-cbc/version.rb
CHANGED
data/lib/ruby-cbc.rb
CHANGED
@@ -4,7 +4,7 @@ require "cbc-wrapper"
|
|
4
4
|
module Cbc
|
5
5
|
end
|
6
6
|
|
7
|
-
files = %w
|
7
|
+
files = %w[
|
8
8
|
conflict_solver
|
9
9
|
model
|
10
10
|
problem
|
@@ -16,7 +16,7 @@ files = %w(
|
|
16
16
|
ilp/term_array
|
17
17
|
ilp/var
|
18
18
|
utils/compressed_row_storage
|
19
|
-
|
19
|
+
]
|
20
20
|
|
21
21
|
files.each do |file|
|
22
22
|
require File.expand_path("../ruby-cbc/#{file}", __FILE__)
|
data/ruby-cbc.gemspec
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
3
|
+
require "ruby-cbc/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
6
|
spec.name = "ruby-cbc"
|
@@ -19,14 +18,16 @@ Gem::Specification.new do |spec|
|
|
19
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
19
|
spec.require_paths = ["lib"]
|
21
20
|
|
22
|
-
spec.add_development_dependency "
|
23
|
-
spec.add_development_dependency "
|
24
|
-
spec.add_development_dependency "rspec"
|
25
|
-
spec.add_development_dependency "rake-compiler"
|
21
|
+
spec.add_development_dependency "benchmark-ips"
|
22
|
+
spec.add_development_dependency "bundler", "~> 2.3"
|
26
23
|
spec.add_development_dependency "pry"
|
27
24
|
spec.add_development_dependency "pry-byebug"
|
28
|
-
spec.add_development_dependency "
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rake-compiler"
|
27
|
+
spec.add_development_dependency "rspec"
|
28
|
+
spec.add_development_dependency "rubocop"
|
29
|
+
spec.add_development_dependency "rubocop-rspec"
|
29
30
|
spec.add_development_dependency "ruby-prof"
|
30
31
|
|
31
|
-
spec.add_dependency "cbc-wrapper",
|
32
|
+
spec.add_dependency "cbc-wrapper", "~> 2.9.9.2"
|
32
33
|
end
|