ruby-cbc 0.3.8 → 0.3.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3d05d2dddacdfb1243b0ccbe0db95ef785002175
4
- data.tar.gz: b9ea06e2a20a3b60a8a28c7a7ccfac5f7af73e3f
3
+ metadata.gz: b400b079a0878a8b069de6806d0a39307ec7cbaa
4
+ data.tar.gz: c12f4fb20c21d4f0a2f56ee300f14ab7af90a693
5
5
  SHA512:
6
- metadata.gz: 4d876f561b81578e8d1b69108e5c4e024eb2c52b66b34eeaade45b4f941d357145a2889e3ad71919bd0a979d7ee3f7a28d92223c263e67777a9a2cce842a8561
7
- data.tar.gz: eb4aed1071260b46aacd4ec4c228a56a1dfb24e8e691c3d4e7ad941348e3521200d747413a75de80fca2bbef3e2a0456f81c66bc23637a9b84dcbe8ca82811e8
6
+ metadata.gz: 7d60c2ca3659d4de0f4c2fc5619b372755b6d403fef0daa62f04117b4fab5a9c3808e9b1f1369e59445ffae46bc08ee31f393984e3714a887c31f2cea5758174
7
+ data.tar.gz: d57f7aad33405975ca485b8a3cdb7ab5da8646ef49a1966b8dc0a6bb6ec5ab66a26236f3293ac0b30e3be23136bde96c2ea66fc0d4623d40e264660368334f9c
data/Rakefile CHANGED
@@ -10,29 +10,17 @@ ensure
10
10
  Dir.chdir(original_dir)
11
11
  end
12
12
 
13
- # RSpec::Core::RakeTask.new(:spec)
14
- #
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
- # ext.tmp_dir = "tmp"
19
- # ext.name = 'cbc_wrapper'
20
- # end
13
+ RSpec::Core::RakeTask.new(:spec)
21
14
 
22
- SHARED_LIBRARY_EXTENSION = RUBY_PLATFORM.include?("darwin") ? 'bundle' : 'so'
23
- EXTENSION = 'lib/ruby-cbc/cbc_wrapper.'+SHARED_LIBRARY_EXTENSION
24
-
25
- desc "Use extconf.rb and make to build the extension."
26
- task :build_extension => EXTENSION
27
-
28
- file EXTENSION => 'ext/ruby-cbc/cbc_wrap.c' do
29
- puts "start"
30
- in_dir('ext/ruby-cbc') do
31
- system("ruby extconf.rb")
32
- system("make")
33
- end
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
+ ext.tmp_dir = "tmp"
19
+ ext.name = 'cbc_wrapper'
34
20
  end
35
21
 
36
- CLEAN.include('ext/ruby-cbc/Makefile', 'ext/ruby-cbc/conftest.dSYM', 'ext/ruby-cbc/mkmf.log', 'ext/ruby-cbc/cbc_wrap.o')
22
+ task :default => [:spec]
37
23
 
38
- task :default => [:build_extension, :spec]
24
+ task :benchmark do
25
+ ruby "test/benchmark.rb"
26
+ end
data/lib/ruby-cbc.rb CHANGED
@@ -15,6 +15,7 @@ ilp/objective
15
15
  ilp/term
16
16
  ilp/term_array
17
17
  ilp/var
18
+ utils/compressed_row_storage
18
19
  )
19
20
 
20
21
  files.each do |file|
@@ -2,66 +2,102 @@ module Cbc
2
2
 
3
3
  class ConflictSolver
4
4
 
5
- def initialize(model)
6
- @model = model
5
+ def initialize(problem)
6
+ # clone the model minus the objective
7
+ @model = Model.new
8
+ @model.vars = problem.model.vars
9
+ @model.constraints = problem.model.constraints
10
+ @problem = problem
7
11
  end
8
12
 
9
- # Assuming there is a conflict
10
13
  def find_conflict
11
- continuous = is_continuous_conflict?
12
- conflict_set = []
13
- all_constraints = @model.constraints
14
- nb_constraints = all_constraints.count
14
+ crs = Util::CompressedRowStorage.from_model(@model)
15
+ continuous = is_continuous_conflict?(crs)
16
+ unless continuous
17
+ p = Problem.from_compressed_row_storage(crs, continuous: false)
18
+ return [] unless infeasible?(p)
19
+ end
20
+ clusters = [crs.nb_constraints]
21
+ max_iter = 1
22
+ conflict_set_size = 0
15
23
  loop do
16
- m = Model.new
17
- m.vars = @model.vars
18
- m.constraints = conflict_set
19
- return conflict_set if infeasible?(m, continuous: continuous)
24
+ range_idxs = first_failing(conflict_set_size, crs, continuous: continuous, max_iterations: max_iter)
25
+ break if range_idxs.nil?
26
+ puts "RANGE #{range_idxs}"
27
+ crs = crs.restrict_to_n_constraints(range_idxs.max + 1)
28
+ crs.move_constraint_to_start(range_idxs)
29
+ clusters.insert(0, range_idxs.size)
30
+ clusters[-1] = range_idxs.min - conflict_set_size
31
+ conflict_set_size += range_idxs.size
32
+
33
+ # Test conflict set
34
+ crs2 = crs.restrict_to_n_constraints(conflict_set_size)
35
+ problem = Problem.from_compressed_row_storage(crs2, continuous: continuous)
36
+ if infeasible?(problem)
37
+ puts "CONFLICT"
38
+ clusters.delete_at(-1)
39
+ break if clusters.size == conflict_set_size
40
+
41
+ crs = crs2
42
+ end
20
43
 
21
- constraint_idx = first_failing(conflict_set, all_constraints, nb_constraints, continuous: continuous)
22
- return conflict_set if !constraint_idx
44
+ nb_clusters_one_constraint = 0
45
+ clusters.reverse_each do |nb_constraints|
46
+ break if nb_constraints > 1
47
+ nb_clusters_one_constraint += 1
48
+ end
49
+ if nb_clusters_one_constraint > 0
50
+ crs.move_constraint_to_start((crs.nb_constraints - nb_clusters_one_constraint)..(crs.nb_constraints - 1))
51
+ clusters[nb_clusters_one_constraint, clusters.size - nb_clusters_one_constraint] =
52
+ clusters[0, clusters.size - nb_clusters_one_constraint]
53
+ clusters[0, nb_clusters_one_constraint] = Array.new(nb_clusters_one_constraint, 1)
54
+ end
23
55
 
24
- nb_constraints = constraint_idx
25
- conflict_set << all_constraints[constraint_idx]
56
+ conflict_set_size = crs.nb_constraints - clusters[-1]
57
+ puts "CLUSTERS #{clusters.inspect}"
58
+ puts "VARS #{crs.col_idx.uniq.size}"
26
59
  end
60
+ crs.model.constraints[0, conflict_set_size]
27
61
  end
28
62
 
29
- def is_continuous_conflict?
30
- # Same model without objective
31
- model = Model.new
32
- model.vars = @model.vars
33
- model.constraints = @model.constraints
34
- infeasible?(model, continuous: true)
63
+ def is_continuous_conflict?(crs)
64
+ problem = Problem.from_compressed_row_storage(crs, continuous: true)
65
+ infeasible?(problem)
35
66
  end
36
67
 
37
68
  private
38
69
  # finds the first constraint from constraints that makes the problem infeasible
39
- def first_failing(conflict_set, constraints, nb_constraints, continuous: false)
40
- min_nb_constraints = 0
41
- max_nb_constraints = nb_constraints + 1
70
+ def first_failing(conflict_set_size, crs, continuous: false, max_iterations: nil)
71
+ min_idx = conflict_set_size
72
+ max_idx = crs.nb_constraints - 1
42
73
 
43
74
  loop do
44
- m = Model.new
45
- m.vars = @model.vars
46
-
47
- half_constraints = (max_nb_constraints + min_nb_constraints) / 2
48
- m.constraints = conflict_set + constraints.take(half_constraints)
49
- if infeasible?(m, continuous: continuous)
50
- max_nb_constraints = half_constraints
75
+ unless max_iterations.nil?
76
+ return min_idx..max_idx if max_iterations <= 0
77
+ max_iterations -= 1
78
+ end
79
+ half_constraint_idx = (max_idx + min_idx) / 2
80
+ puts "Refining: [#{min_idx}:#{max_idx}] -> #{half_constraint_idx}"
81
+ crs2 = crs.restrict_to_n_constraints(half_constraint_idx + 1)
82
+ problem = Problem.from_compressed_row_storage(crs2, continuous: continuous)
83
+ if infeasible?(problem)
84
+ max_idx = half_constraint_idx
85
+ puts " INFEAS"
51
86
  else
52
- min_nb_constraints = half_constraints
87
+ min_idx = half_constraint_idx + 1
88
+ puts " FEAS"
53
89
  end
54
- if max_nb_constraints - min_nb_constraints <= 1
55
- return nil if max_nb_constraints > constraints.count
56
- return max_nb_constraints - 1
90
+ if max_idx == min_idx
91
+ puts "found: max = #{max_idx} min = #{min_idx} nb = #{crs.nb_constraints}"
92
+ return nil if max_idx > crs.nb_constraints
93
+ return min_idx..max_idx
57
94
  end
58
95
  end
59
96
  # Shouldn't come here if the whole problem is infeasible
60
97
  return nil
61
98
  end
62
99
 
63
- def infeasible?(model, continuous: false)
64
- problem = Problem.new(model, continuous: continuous)
100
+ def infeasible?(problem)
65
101
  problem.solve
66
102
  problem.proven_infeasible?
67
103
  end
@@ -19,7 +19,7 @@ module Ilp
19
19
  end
20
20
 
21
21
  def to_function_s
22
- "#{function_name || 'constraint'}(#{vars.join(', ')})"
22
+ "#{function_name || 'constraint'}(#{vars.map(&:name).join(', ')})"
23
23
  end
24
24
 
25
25
  def to_s
@@ -1,5 +1,3 @@
1
- require "set"
2
-
3
1
  module Cbc
4
2
 
5
3
  INF = 1.0 / 0.0 # Useful for ranges
@@ -24,7 +22,7 @@ module Cbc
24
22
  attr_accessor :vars, :constraints, :objective, :name
25
23
 
26
24
  def initialize(name: "ILP Problem")
27
- @vars = Set.new
25
+ @vars = []
28
26
  @constraints = []
29
27
  @objective = nil
30
28
  @name = name
@@ -82,7 +80,7 @@ module Cbc
82
80
  end
83
81
 
84
82
  def to_problem
85
- Cbc::Problem.new(self)
83
+ Cbc::Problem.from_model(self)
86
84
  end
87
85
 
88
86
  def to_s
@@ -1,55 +1,80 @@
1
1
  module Cbc
2
2
  class Problem
3
3
 
4
- attr_reader :model
4
+ attr_accessor :model, :variable_index, :crs
5
5
 
6
- def initialize(model, continuous: false)
7
-
8
- @int_arrays = []
9
- @double_arrays = []
6
+ def self.from_model(model, continuous: false)
7
+ crs = Util::CompressedRowStorage.from_model(model)
8
+ from_compressed_row_storage(crs, continuous: continuous)
9
+ end
10
10
 
11
- @model = model
12
- @variables = {}
13
- vars = model.vars
14
- vars_data = {}
15
- vars.each_with_index do |v, idx|
16
- @variables[v] = idx
17
- vars_data[v] = VarData.new(v, idx, [], [])
11
+ def self.from_compressed_row_storage(crs, continuous: false)
12
+ new.tap do |p|
13
+ p.model = crs.model
14
+ p.variable_index = crs.variable_index
15
+ p.crs = crs
16
+ p.create_cbc_problem(continuous: continuous)
18
17
  end
18
+ end
19
19
 
20
- model.constraints.each_with_index do |c, idx|
21
- c.terms.each do |term|
22
- v_data = vars_data[term.var]
23
- v_data.constraints << idx
24
- v_data.coefs << term.mult
25
- end
20
+ CCS = Struct.new(:col_ptr, :row_idx, :values) do
21
+ def nb_vars
22
+ col_ptr.size - 1
26
23
  end
24
+ end
27
25
 
28
- indexes = []
29
- rows = []
30
- coefs = []
26
+ def self.crs_to_ccs(crs)
27
+ nb_per_column = Array.new(crs.col_idx.max.to_i + 1, 0)
28
+ nb_values = crs.values.size
31
29
 
32
- vars.each_with_index do |v, idx|
33
- v_data = vars_data[v]
34
- indexes[idx] = rows.count
35
- rows.concat v_data.constraints
36
- coefs.concat v_data.coefs
30
+ crs.col_idx.each { |col_idx| nb_per_column[col_idx] += 1 }
31
+
32
+ ccs = CCS.new(Array.new(nb_per_column.size + 1), Array.new(nb_values), Array.new(nb_values))
33
+ ccs.col_ptr[0] = 0
34
+ idx = 0
35
+ while idx < nb_per_column.size
36
+ ccs.col_ptr[idx + 1] = ccs.col_ptr[idx] + nb_per_column[idx]
37
+ idx += 1
37
38
  end
38
39
 
39
- indexes << rows.count
40
+ cols_idx = ccs.col_ptr.clone
41
+ row_idx = 0
42
+ end_row_idx = crs.row_ptr.size - 1
43
+ while row_idx < end_row_idx do
44
+ current_idx = crs.row_ptr[row_idx]
45
+ last_idx = crs.row_ptr[row_idx + 1] - 1
46
+ while current_idx <= last_idx do
47
+ col_idx = crs.col_idx[current_idx]
48
+ ccs_col_idx = cols_idx[col_idx]
49
+ cols_idx[col_idx] += 1
50
+ ccs.row_idx[ccs_col_idx] = row_idx
51
+ ccs.values[ccs_col_idx] = crs.values[current_idx]
52
+ current_idx += 1
53
+ end
54
+ row_idx += 1
55
+ end
56
+ ccs
57
+ end
40
58
 
41
- objective = Array.new(vars.count, 0)
59
+ def create_cbc_problem(continuous: false)
60
+ @int_arrays = []
61
+ @double_arrays = []
62
+
63
+ ccs = self.class.crs_to_ccs(@crs)
64
+ objective = Array.new(ccs.nb_vars, 0)
42
65
  if model.objective
43
66
  model.objective.terms.each do |term|
44
- objective[vars_data[term.var].col_idx] = term.mult
67
+ objective[@variable_index[term.var]] = term.mult
45
68
  end
46
69
  end
47
70
 
48
71
  @cbc_model = Cbc_wrapper.Cbc_newModel
49
- Cbc_wrapper.Cbc_loadProblem(@cbc_model, model.vars.count, model.constraints.count,
50
- to_int_array(indexes), to_int_array(rows),
51
- to_double_array(coefs), nil, nil, to_double_array(objective),
52
- nil, nil)
72
+ Cbc_wrapper.Cbc_loadProblem(
73
+ @cbc_model, ccs.nb_vars, @crs.nb_constraints,
74
+ to_int_array(ccs.col_ptr), to_int_array(ccs.row_idx),
75
+ to_double_array(ccs.values), nil, nil, to_double_array(objective),
76
+ nil, nil)
77
+
53
78
 
54
79
  # Segmentation errors when setting name
55
80
  # Cbc_wrapper.Cbc_setProblemName(@cbc_model, model.name) if model.name
@@ -59,18 +84,15 @@ module Cbc
59
84
  Cbc_wrapper.Cbc_setObjSense(@cbc_model, obj_sense)
60
85
  end
61
86
 
62
- model.constraints.each_with_index do |c, idx|
63
- case c.type
64
- when Ilp::Constraint::LESS_OR_EQ
65
- Cbc_wrapper.Cbc_setRowUpper(@cbc_model, idx, c.bound)
66
- when Ilp::Constraint::GREATER_OR_EQ
67
- Cbc_wrapper.Cbc_setRowLower(@cbc_model, idx, c.bound)
68
- when Ilp::Constraint::EQUALS
69
- Cbc_wrapper.Cbc_setRowUpper(@cbc_model, idx, c.bound)
70
- Cbc_wrapper.Cbc_setRowLower(@cbc_model, idx, c.bound)
71
- end
87
+ idx = 0
88
+ while idx < @crs.nb_constraints do
89
+ c = model.constraints[idx]
90
+ set_constraint_bounds(c, idx)
91
+ idx += 1
72
92
  end
73
- model.vars.each_with_index do |v, idx|
93
+ idx = 0
94
+ while idx < ccs.nb_vars do
95
+ v = model.vars[idx]
74
96
  if continuous
75
97
  Cbc_wrapper.Cbc_setContinuous(@cbc_model, idx)
76
98
  else
@@ -83,14 +105,28 @@ module Cbc
83
105
  end
84
106
  Cbc_wrapper.Cbc_setColLower(@cbc_model, idx, v.lower_bound) unless v.lower_bound.nil?
85
107
  Cbc_wrapper.Cbc_setColUpper(@cbc_model, idx, v.upper_bound) unless v.upper_bound.nil?
108
+ idx += 1
86
109
  end
87
110
 
88
111
  ObjectSpace.define_finalizer(self, self.class.finalizer(@cbc_model, @int_arrays, @double_arrays))
89
112
 
90
113
  @default_solve_params = {
91
- log: 0,
92
- }
114
+ log: 0,
115
+ }
116
+
117
+
118
+ end
93
119
 
120
+ def set_constraint_bounds(c, idx)
121
+ case c.type
122
+ when Ilp::Constraint::LESS_OR_EQ
123
+ Cbc_wrapper.Cbc_setRowUpper(@cbc_model, idx, c.bound)
124
+ when Ilp::Constraint::GREATER_OR_EQ
125
+ Cbc_wrapper.Cbc_setRowLower(@cbc_model, idx, c.bound)
126
+ when Ilp::Constraint::EQUALS
127
+ Cbc_wrapper.Cbc_setRowUpper(@cbc_model, idx, c.bound)
128
+ Cbc_wrapper.Cbc_setRowLower(@cbc_model, idx, c.bound)
129
+ end
94
130
  end
95
131
 
96
132
  def solve(params = {})
@@ -99,10 +135,12 @@ module Cbc
99
135
  end
100
136
  Cbc_wrapper.Cbc_solve(@cbc_model)
101
137
  @solution = Cbc_wrapper::DoubleArray.frompointer(Cbc_wrapper.Cbc_getColSolution(@cbc_model))
138
+ @double_arrays << @solution
139
+ @solution
102
140
  end
103
141
 
104
142
  def value_of(var)
105
- idx = @variables[var]
143
+ idx = @variable_index[var]
106
144
  return nil if idx.nil?
107
145
  if var.kind == Ilp::Var::CONTINUOUS_KIND
108
146
  @solution[idx]
@@ -141,7 +179,7 @@ module Cbc
141
179
  end
142
180
 
143
181
  def find_conflict
144
- @conflict_set ||= ConflictSolver.new(model).find_conflict
182
+ @conflict_set ||= ConflictSolver.new(self).find_conflict
145
183
  end
146
184
 
147
185
  def find_conflict_vars
@@ -163,21 +201,25 @@ module Cbc
163
201
  private
164
202
 
165
203
  def to_int_array(array)
166
- c_array = Cbc_wrapper::IntArray.new(array.count)
167
- array.each_with_index { |value, idx| c_array[idx] = value }
204
+ c_array = Cbc_wrapper::IntArray.new(array.size)
205
+ idx = 0
206
+ while idx < array.size do
207
+ c_array[idx] = array[idx]
208
+ idx += 1
209
+ end
168
210
  @int_arrays << c_array
169
211
  c_array
170
212
  end
171
213
 
172
214
  def to_double_array(array)
173
- c_array = Cbc_wrapper::DoubleArray.new(array.count)
174
- array.each_with_index { |value, idx| c_array[idx] = value }
215
+ c_array = Cbc_wrapper::DoubleArray.new(array.size)
216
+ idx = 0
217
+ while idx < array.size do
218
+ c_array[idx] = array[idx]
219
+ idx += 1
220
+ end
175
221
  @double_arrays << c_array
176
222
  c_array
177
223
  end
178
-
179
- VarData = Struct.new(:variable, :col_idx, :constraints, :coefs)
180
224
  end
181
-
182
-
183
225
  end
@@ -0,0 +1,82 @@
1
+ module Util
2
+ class CompressedRowStorage
3
+
4
+ attr_accessor :model, :variable_index, :row_ptr, :col_idx, :values
5
+
6
+ def self.from_model(model)
7
+ new.tap do |crs|
8
+ crs.model = model
9
+ crs.variable_index = {}
10
+ idx = 0
11
+ while idx < model.vars.size do
12
+ v = model.vars[idx]
13
+ crs.variable_index[v] = idx
14
+ idx += 1
15
+ end
16
+ crs.fill_matrix
17
+ end
18
+ end
19
+
20
+ def nb_constraints
21
+ row_ptr.count - 1
22
+ end
23
+
24
+ def fill_matrix
25
+ nb_values = model.constraints.map { |c| c.terms.count }.inject(:+) || 0
26
+ @row_ptr = Array.new(model.constraints.count)
27
+ @col_idx = Array.new(nb_values)
28
+ @values = Array.new(nb_values)
29
+
30
+ nb_cols = 0
31
+ c_idx = 0
32
+ while c_idx < @model.constraints.size do
33
+ constraint = @model.constraints[c_idx]
34
+ @row_ptr[c_idx] = nb_cols
35
+ nb_insert = constraint.terms.count
36
+ @col_idx[nb_cols, nb_insert] = constraint.terms.map { |term| variable_index[term.var] }
37
+ @values[nb_cols, nb_insert] = constraint.terms.map { |term| term.mult }
38
+ nb_cols += nb_insert
39
+ c_idx += 1
40
+ end
41
+ @row_ptr << @col_idx.count
42
+ end
43
+
44
+ def restrict_to_n_constraints(nb_constraints)
45
+ length_of_values = @row_ptr[nb_constraints]
46
+ CompressedRowStorage.new.tap do |crs|
47
+ crs.model = @model
48
+ crs.variable_index = @variable_index
49
+ crs.row_ptr = @row_ptr[0, nb_constraints + 1]
50
+ crs.col_idx = @col_idx[0, length_of_values]
51
+ crs.values = @values[0, length_of_values]
52
+ end
53
+ end
54
+
55
+ def move_constraint_to_start(range_idxs)
56
+ # Move in the model
57
+ constraints = model.constraints[range_idxs]
58
+ @model.constraints = @model.constraints.clone
59
+ @model.constraints[constraints.count, range_idxs.max] = model.constraints[0, range_idxs.min]
60
+ @model.constraints[0, constraints.count] = constraints
61
+
62
+ # Move in the matrix
63
+ constraint_start_idx = @row_ptr[range_idxs.min]
64
+ nb_vars = @row_ptr[range_idxs.max + 1] - constraint_start_idx
65
+ offset= @row_ptr[range_idxs.min]
66
+ new_begin = @row_ptr[range_idxs].map! { |idx| idx - offset }
67
+ ((range_idxs.count)..(range_idxs.max)).reverse_each do |idx|
68
+ @row_ptr[idx] = @row_ptr[idx - range_idxs.count] + nb_vars
69
+ end
70
+ @row_ptr[0, range_idxs.count] = new_begin
71
+ move_block_to_start(@col_idx, constraint_start_idx, nb_vars)
72
+ move_block_to_start(@values, constraint_start_idx, nb_vars)
73
+ end
74
+
75
+ def move_block_to_start(array, block_start_idx, nb_values)
76
+ to_move = array[block_start_idx, nb_values]
77
+ array[nb_values, block_start_idx] = array[0, block_start_idx]
78
+ array[0, nb_values] = to_move
79
+ end
80
+
81
+ end
82
+ end
@@ -1,3 +1,3 @@
1
1
  module Cbc
2
- VERSION = "0.3.8"
2
+ VERSION = "0.3.9"
3
3
  end
data/ruby-cbc.gemspec CHANGED
@@ -25,6 +25,8 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "rake-compiler"
26
26
  spec.add_development_dependency "pry"
27
27
  spec.add_development_dependency "pry-byebug"
28
+ spec.add_development_dependency "benchmark-ips"
29
+ spec.add_development_dependency "ruby-prof"
28
30
 
29
31
  spec.add_dependency "cbc-wrapper", '~> 2.9.7.2'
30
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-cbc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guillaume Verger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-12 00:00:00.000000000 Z
11
+ date: 2016-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,6 +94,34 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: benchmark-ips
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: ruby-prof
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: cbc-wrapper
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -134,6 +162,7 @@ files:
134
162
  - lib/ruby-cbc/ilp/var.rb
135
163
  - lib/ruby-cbc/model.rb
136
164
  - lib/ruby-cbc/problem.rb
165
+ - lib/ruby-cbc/utils/compressed_row_storage.rb
137
166
  - lib/ruby-cbc/version.rb
138
167
  - ruby-cbc.gemspec
139
168
  homepage: https://github.com/gverger/ruby-cbc
@@ -161,4 +190,3 @@ signing_key:
161
190
  specification_version: 4
162
191
  summary: Wrapper around Cbc Linear Programming Solver
163
192
  test_files: []
164
- has_rdoc: