Class: Cbc::Problem

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby-cbc/problem.rb

Defined Under Namespace

Classes: VarData

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ Problem

Returns a new instance of Problem.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/ruby-cbc/problem.rb', line 6

def initialize(model)

  @int_arrays = []
  @double_arrays = []

  @model = model
  @variables = {}
  vars = model.vars
  vars_data = {}
  vars.each_with_index do |v, idx|
    @variables[v] = idx
    vars_data[v] = VarData.new(v, idx, [], [])
  end

  model.constraints.each_with_index do |c, idx|
    c.terms.each do |term|
      v_data = vars_data[term.var]
      v_data.constraints << idx
      v_data.coefs << term.mult
    end
  end

  indexes = []
  rows = []
  coefs = []

  vars.each_with_index do |v, idx|
    v_data = vars_data[v]
    indexes[idx] = rows.count
    rows.concat v_data.constraints
    coefs.concat v_data.coefs
  end

  indexes << rows.count

  objective = Array.new(vars.count, 0)
  if model.objective
    model.objective.terms.each do |term|
      objective[vars_data[term.var].col_idx] = term.mult
    end
  end

  @cbc_model = Cbc_wrapper.Cbc_newModel
  Cbc_wrapper.Cbc_loadProblem(@cbc_model, model.vars.count, model.constraints.count,
                             to_int_array(indexes), to_int_array(rows),
                             to_double_array(coefs), nil, nil, to_double_array(objective),
                             nil, nil)

  # Segmentation errors when setting name
  # Cbc_wrapper.Cbc_setProblemName(@cbc_model, model.name) if model.name

  if model.objective
    obj_sense = model.objective.objective_function == Ilp::Objective::MINIMIZE ? 1 : -1
    Cbc_wrapper.Cbc_setObjSense(@cbc_model, obj_sense)
  end

  model.constraints.each_with_index do |c, idx|
    case c.type
    when Ilp::Constraint::LESS_OR_EQ
      Cbc_wrapper.Cbc_setRowUpper(@cbc_model, idx, c.bound)
    when Ilp::Constraint::GREATER_OR_EQ
      Cbc_wrapper.Cbc_setRowLower(@cbc_model, idx, c.bound)
    when Ilp::Constraint::EQUALS
      Cbc_wrapper.Cbc_setRowUpper(@cbc_model, idx, c.bound)
      Cbc_wrapper.Cbc_setRowLower(@cbc_model, idx, c.bound)
    end
  end
  model.vars.each_with_index do |v, idx|
    case v.kind
    when Ilp::Var::INTEGER_KIND
      Cbc_wrapper.Cbc_setInteger(@cbc_model, idx)
    when Ilp::Var::BINARY_KIND
      Cbc_wrapper.Cbc_setInteger(@cbc_model, idx)
      v.bounds = 0..1
    when Ilp::Var::CONTINUOUS_KIND
      Cbc_wrapper.Cbc_setContinuous(@cbc_model, idx)
    end
    Cbc_wrapper.Cbc_setColLower(@cbc_model, idx, v.lower_bound) unless v.lower_bound.nil?
    Cbc_wrapper.Cbc_setColUpper(@cbc_model, idx, v.upper_bound) unless v.upper_bound.nil?
  end

  ObjectSpace.define_finalizer(self, self.class.finalizer(@cbc_model, @int_arrays, @double_arrays))

  @default_solve_params = {
      log: 0,
    }

end

Instance Attribute Details

#modelObject (readonly)

Returns the value of attribute model.



4
5
6
# File 'lib/ruby-cbc/problem.rb', line 4

def model
  @model
end

Class Method Details

.finalizer(cbc_model, int_arrays, double_arrays) ⇒ Object



150
151
152
153
154
155
156
# File 'lib/ruby-cbc/problem.rb', line 150

def self.finalizer(cbc_model, int_arrays, double_arrays)
  proc do
    Cbc_wrapper.Cbc_deleteModel(cbc_model)
    int_arrays.each { |ar| Cbc_wrapper.delete_intArray(ar) }
    double_arrays.each { |ar| Cbc_wrapper.delete_doubleArray(ar) }
  end
end

Instance Method Details

#best_boundObject

Returns the best know bound so far



138
139
140
# File 'lib/ruby-cbc/problem.rb', line 138

def best_bound
  Cbc_wrapper.Cbc_getBestPossibleObjValue(@cbc_model)
end

#find_conflictObject



142
143
144
# File 'lib/ruby-cbc/problem.rb', line 142

def find_conflict
  @conflict_set ||= ConflictSolver.new(model).find_conflict
end

#find_conflict_varsObject



146
147
148
# File 'lib/ruby-cbc/problem.rb', line 146

def find_conflict_vars
  @conflict_vars ||= find_conflict.map(&:vars).flatten.uniq
end

#objective_valueObject



133
134
135
# File 'lib/ruby-cbc/problem.rb', line 133

def objective_value
  Cbc_wrapper.Cbc_getObjValue(@cbc_model)
end

#proven_infeasible?Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/ruby-cbc/problem.rb', line 121

def proven_infeasible?
  Cbc_wrapper.Cbc_isProvenInfeasible(@cbc_model) == 1
end

#proven_optimal?Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/ruby-cbc/problem.rb', line 117

def proven_optimal?
  Cbc_wrapper.Cbc_isProvenOptimal(@cbc_model) == 1
end

#set_time_limit(seconds) ⇒ Object



113
114
115
# File 'lib/ruby-cbc/problem.rb', line 113

def set_time_limit(seconds)
  @default_solve_params[:sec] = seconds
end

#solution_limit_reached?Boolean

Returns:

  • (Boolean)


129
130
131
# File 'lib/ruby-cbc/problem.rb', line 129

def solution_limit_reached?
  Cbc_wrapper.Cbc_isSolutionLimitReached(@cbc_model) == 1
end

#solve(params = {}) ⇒ Object



95
96
97
98
99
100
101
# File 'lib/ruby-cbc/problem.rb', line 95

def solve(params = {})
  @default_solve_params.merge(params).each do |name, value|
    Cbc_wrapper.Cbc_setParameter(@cbc_model, name.to_s, value.to_s)
  end
  Cbc_wrapper.Cbc_solve(@cbc_model)
  @solution = Cbc_wrapper::DoubleArray.frompointer(Cbc_wrapper.Cbc_getColSolution(@cbc_model))
end

#time_limit_reached?Boolean

Returns:

  • (Boolean)


125
126
127
# File 'lib/ruby-cbc/problem.rb', line 125

def time_limit_reached?
  Cbc_wrapper.Cbc_isSecondsLimitReached(@cbc_model) == 1
end

#value_of(var) ⇒ Object



103
104
105
106
107
108
109
110
111
# File 'lib/ruby-cbc/problem.rb', line 103

def value_of(var)
  idx = @variables[var]
  return nil if idx.nil?
  if var.kind == Ilp::Var::CONTINUOUS_KIND
    @solution[idx]
  else
    @solution[idx].round
  end
end

#writeObject



158
159
160
# File 'lib/ruby-cbc/problem.rb', line 158

def write
  Cbc_wrapper.Cbc_writeMps(@cbc_model, "test")
end