mipper 0.0.4
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 +7 -0
- data/lib/mipper/cbc/ext.rb +36 -0
- data/lib/mipper/cbc/model.rb +174 -0
- data/lib/mipper/cbc.rb +3 -0
- data/lib/mipper/constraint.rb +17 -0
- data/lib/mipper/expression.rb +53 -0
- data/lib/mipper/glpk/ext/constants.rb +587 -0
- data/lib/mipper/glpk/ext/structs.rb +28 -0
- data/lib/mipper/glpk/ext.rb +43 -0
- data/lib/mipper/glpk/model.rb +186 -0
- data/lib/mipper/glpk.rb +3 -0
- data/lib/mipper/gurobi/env.rb +25 -0
- data/lib/mipper/gurobi/ext/constants.rb +1899 -0
- data/lib/mipper/gurobi/ext.rb +47 -0
- data/lib/mipper/gurobi/model.rb +246 -0
- data/lib/mipper/gurobi.rb +4 -0
- data/lib/mipper/lp_solve/ext/constants.rb +2075 -0
- data/lib/mipper/lp_solve/ext.rb +35 -0
- data/lib/mipper/lp_solve/model.rb +173 -0
- data/lib/mipper/lp_solve.rb +4 -0
- data/lib/mipper/model.rb +92 -0
- data/lib/mipper/util.rb +5 -0
- data/lib/mipper/variable.rb +79 -0
- data/lib/mipper.rb +11 -0
- metadata +81 -0
@@ -0,0 +1,186 @@
|
|
1
|
+
module MIPPeR
|
2
|
+
class GLPKModel < Model
|
3
|
+
attr_reader :ptr
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
super
|
7
|
+
|
8
|
+
@var_count = 0
|
9
|
+
@constr_count = 0
|
10
|
+
|
11
|
+
# Constraint matrix initialization (see #add_constraints)
|
12
|
+
@ia = [0]
|
13
|
+
@ja = [0]
|
14
|
+
@ar = [0]
|
15
|
+
|
16
|
+
# Disable terminal output
|
17
|
+
GLPK.glp_term_out GLPK::GLP_OFF
|
18
|
+
|
19
|
+
# Construct a new model
|
20
|
+
@ptr = FFI::AutoPointer.new GLPK.glp_create_prob,
|
21
|
+
GLPK.method(:glp_delete_prob)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Write the model to a file
|
25
|
+
def write(filename)
|
26
|
+
ret = GLPK.glp_write_lp @ptr, 0, filename
|
27
|
+
fail if ret != 0
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set the sense of the model
|
31
|
+
def sense=(sense)
|
32
|
+
@sense = sense
|
33
|
+
sense = sense == :min ? GLPK::GLP_MIN : GLPK::GLP_MAX
|
34
|
+
GLPK.glp_set_obj_dir @ptr, sense
|
35
|
+
end
|
36
|
+
|
37
|
+
# Optimize the model
|
38
|
+
def optimize
|
39
|
+
# Ensure pending variables and constraints are added
|
40
|
+
update
|
41
|
+
|
42
|
+
# Run the solver and save the status for later
|
43
|
+
iocp = GLPK::IOCP.new
|
44
|
+
GLPK.glp_init_iocp iocp
|
45
|
+
iocp[:presolve] = GLPK::GLP_ON
|
46
|
+
@status = GLPK.glp_intopt @ptr, iocp
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get the status of the model
|
50
|
+
def status
|
51
|
+
case @status
|
52
|
+
when 0, GLPK::GLP_EMIPGAP
|
53
|
+
:optimized
|
54
|
+
when GLPK::GLP_EBOUND, GLPK::GLP_EROOT, GLPK::GLP_ENOPFS
|
55
|
+
:invalid
|
56
|
+
else
|
57
|
+
:unknown
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# The value of the objective function
|
62
|
+
def objective_value
|
63
|
+
GLPK.glp_mip_obj_val @ptr
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get the value of a variable from the model
|
67
|
+
def variable_value(var)
|
68
|
+
GLPK.glp_mip_col_val(@ptr, var.index)
|
69
|
+
end
|
70
|
+
|
71
|
+
def set_variable_bounds(var_index, lb, ub)
|
72
|
+
# Determine the type of the variable bounds
|
73
|
+
if lb == ub
|
74
|
+
type = GLPK::GLP_FX
|
75
|
+
elsif lb.finite?
|
76
|
+
type = ub.finite? ? GLPK::GLP_DB : GLPK::GLP_LO
|
77
|
+
else
|
78
|
+
type = ub.finite? ? GLPK::GLP_UP : GLPK::GLP_FR
|
79
|
+
end
|
80
|
+
|
81
|
+
# Set the bounds on the variable
|
82
|
+
GLPK.glp_set_col_bnds(@ptr, var_index, type, lb, ub)
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
# Add multiple variables to the model simultaneously
|
88
|
+
def add_variables(vars)
|
89
|
+
# Store all the variables in the model
|
90
|
+
GLPK.glp_add_cols(@ptr, vars.length)
|
91
|
+
vars.each { |var| store_variable var }
|
92
|
+
end
|
93
|
+
|
94
|
+
# Add multiple constraints at once
|
95
|
+
def add_constraints(constrs)
|
96
|
+
GLPK.glp_add_rows(@ptr, constrs.length)
|
97
|
+
|
98
|
+
# Store each constraint and initialize a matrix used to hold
|
99
|
+
# the coefficients of each value in the constraint matrix
|
100
|
+
#
|
101
|
+
# * ia - row (constraint) index
|
102
|
+
# * ja - column (variable) index
|
103
|
+
# * ar - constraint coefficient
|
104
|
+
constrs.each do |constr|
|
105
|
+
store_constraint constr
|
106
|
+
constr.expression.terms.each do |var, coeff|
|
107
|
+
@ia << constr.instance_variable_get(:@index)
|
108
|
+
@ja << var.instance_variable_get(:@index)
|
109
|
+
@ar << coeff
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
ia_buffer = FFI::MemoryPointer.new :pointer, @ia.length
|
114
|
+
ia_buffer.write_array_of_int @ia
|
115
|
+
ja_buffer = FFI::MemoryPointer.new :pointer, @ja.length
|
116
|
+
ja_buffer.write_array_of_int @ja
|
117
|
+
ar_buffer = FFI::MemoryPointer.new :pointer, @ar.length
|
118
|
+
ar_buffer.write_array_of_double @ar
|
119
|
+
|
120
|
+
GLPK.glp_load_matrix(@ptr, @ar.length - 1, ia_buffer, ja_buffer,
|
121
|
+
ar_buffer)
|
122
|
+
|
123
|
+
@constraints.concat constrs
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
# Save the constraint to the model and update the constraint pointers
|
129
|
+
def store_constraint(constr)
|
130
|
+
# Update the constraint to track the index in the model
|
131
|
+
index = @constr_count + 1
|
132
|
+
constr.instance_variable_set :@model, self
|
133
|
+
constr.instance_variable_set :@index, index
|
134
|
+
@constr_count += 1
|
135
|
+
|
136
|
+
# Set constraint properties
|
137
|
+
GLPK.glp_set_row_name(@ptr, index, constr.name)
|
138
|
+
|
139
|
+
case constr.sense
|
140
|
+
when :==
|
141
|
+
lb = ub = constr.rhs
|
142
|
+
type = GLPK::GLP_FX
|
143
|
+
when :>=
|
144
|
+
lb = constr.rhs
|
145
|
+
ub = Float::INFINITY
|
146
|
+
type = GLPK::GLP_LO
|
147
|
+
when :<=
|
148
|
+
lb = -Float::INFINITY
|
149
|
+
ub = constr.rhs
|
150
|
+
type = GLPK::GLP_UP
|
151
|
+
end
|
152
|
+
GLPK.glp_set_row_bnds(@ptr, index, type, lb, ub)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Save the variable to the model and update the variable pointers
|
156
|
+
def store_variable(var)
|
157
|
+
# Update the variable to track the index in the model
|
158
|
+
index = @var_count + 1
|
159
|
+
var.instance_variable_set :@model, self
|
160
|
+
var.instance_variable_set :@index, index
|
161
|
+
@var_count += 1
|
162
|
+
|
163
|
+
@variables << var
|
164
|
+
|
165
|
+
# Set variable properties
|
166
|
+
GLPK.glp_set_col_name(@ptr, index, var.name)
|
167
|
+
GLPK.glp_set_col_kind(@ptr, index, glpk_type(var.type))
|
168
|
+
GLPK.glp_set_obj_coef(@ptr, index, var.coefficient)
|
169
|
+
set_variable_bounds index, var.lower_bound, var.upper_bound
|
170
|
+
end
|
171
|
+
|
172
|
+
# Get the constant GLPK uses to represent our variable types
|
173
|
+
def glpk_type(type)
|
174
|
+
case type
|
175
|
+
when :integer
|
176
|
+
GLPK::GLP_IV
|
177
|
+
when :binary
|
178
|
+
GLPK::GLP_BV
|
179
|
+
when :continuous
|
180
|
+
GLPK::GLP_CV
|
181
|
+
else
|
182
|
+
fail type
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
data/lib/mipper/glpk.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module MIPPeR
|
2
|
+
module Gurobi
|
3
|
+
class Environment
|
4
|
+
attr_reader :ptr
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
# Create a new environment object
|
8
|
+
@ptr = FFI::MemoryPointer.new :pointer
|
9
|
+
Gurobi.GRBloadenv @ptr, nil
|
10
|
+
@ptr = @ptr.read_pointer
|
11
|
+
|
12
|
+
# Disable output
|
13
|
+
Gurobi.GRBsetintparam @ptr, Gurobi::GRB_INT_PAR_OUTPUTFLAG, 0
|
14
|
+
|
15
|
+
# Ensure the environment is freed
|
16
|
+
ObjectSpace.define_finalizer self, self.class.finalize(@ptr)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Free the environment
|
20
|
+
def self.finalize(ptr)
|
21
|
+
proc { Gurobi.GRBfreeenv ptr }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|