ruby-cbc 0.3.8 → 0.3.9

Sign up to get free protection for your applications and to get access to all the features.
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: