Class: Opt::Solvers::GlpkSolver

Inherits:
AbstractSolver show all
Defined in:
lib/opt/solvers/glpk_solver.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from AbstractSolver

supports_semi_continuous_variables?, supports_semi_integer_variables?, supports_type?

Class Method Details

.available?Boolean

Returns:

  • (Boolean)


64
65
66
# File 'lib/opt/solvers/glpk_solver.rb', line 64

def self.available?
  defined?(Glpk)
end

.supported_typesObject



68
69
70
# File 'lib/opt/solvers/glpk_solver.rb', line 68

def self.supported_types
  [:lp, :mip]
end

Instance Method Details

#solve(sense:, start:, index:, value:, col_lower:, col_upper:, obj:, row_lower:, row_upper:, offset:, verbose:, time_limit:, vars:) ⇒ Object



4
5
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
# File 'lib/opt/solvers/glpk_solver.rb', line 4

def solve(sense:, start:, index:, value:, col_lower:, col_upper:, obj:, row_lower:, row_upper:, offset:, verbose:, time_limit:, vars:, **)
  col_kind =
    vars.map do |v|
      case v
      when Binary
        :binary
      when Integer
        :integer
      else
        :continuous
      end
    end

  mat_ia = []
  mat_ja = []
  mat_ar = []
  start.each_with_index do |s, j|
    rng = s...start[j + 1]
    index[rng].zip(value[rng]) do |i, v|
      mat_ia << i + 1
      mat_ja << j + 1
      mat_ar << v
    end
  end

  model =
    Glpk.load_problem(
      obj_dir: sense,
      obj_coef: obj,
      mat_ia: mat_ia,
      mat_ja: mat_ja,
      mat_ar: mat_ar,
      col_kind: col_kind,
      col_lower: col_lower,
      col_upper: col_upper,
      row_lower: row_lower,
      row_upper: row_upper,
    )
  res = model.solve(message_level: verbose ? 3 : 0, time_limit: time_limit)
  model.free if model.respond_to?(:free)

  status =
    case res[:status]
    when :no_feasible, :no_primal_feasible
      :infeasible
    else
      res[:status]
    end

  if status == :optimal && !res[:obj_val].finite?
    status = :unbounded
  end

  {
    status: status,
    objective: res[:obj_val] + offset,
    x: res[:col_primal]
  }
end