class MIPPeR::GurobiModel
A linear programming model using the Gurobi
solver
Attributes
environment[R]
ptr[R]
Public Class Methods
new()
click to toggle source
Calls superclass method
# File lib/mipper/gurobi/model.rb, line 6 def initialize fail unless MIPPeR.const_defined?(:Gurobi) super @var_count = 0 @environment = Gurobi::Environment.new @ptr = FFI::MemoryPointer.new :pointer Gurobi.GRBnewmodel @environment.ptr, @ptr, 'model', 0, nil, nil, nil, nil, nil @ptr = @ptr.read_pointer # Ensure the model is freed ObjectSpace.define_finalizer self, self.class.finalize(@ptr) end
Private Class Methods
finalize(ptr)
click to toggle source
Free the model
# File lib/mipper/gurobi/model.rb, line 185 def self.finalize(ptr) proc { Gurobi.GRBfreemodel ptr } end
Public Instance Methods
compute_iis()
click to toggle source
Compute an irreducible inconsistent subsytem for the model
# File lib/mipper/gurobi/model.rb, line 62 def compute_iis ret = Gurobi.GRBcomputeIIS @ptr fail if ret != 0 end
optimize()
click to toggle source
Optimize the model
# File lib/mipper/gurobi/model.rb, line 51 def optimize # Ensure pending variables and constraints are added update ret = Gurobi.GRBoptimize @ptr fail if ret != 0 save_solution end
sense=(sense)
click to toggle source
Set the sense of the model
# File lib/mipper/gurobi/model.rb, line 43 def sense=(sense) @sense = sense sense = sense == :min ? Gurobi::GRB_MINIMIZE : Gurobi::GRB_MAXIMIZE ret = Gurobi.GRBsetintattr @ptr, Gurobi::GRB_INT_ATTR_MODELSENSE, sense fail if ret != 0 end
set_variable_bounds(var_index, lb, ub)
click to toggle source
# File lib/mipper/gurobi/model.rb, line 67 def set_variable_bounds(var_index, lb, ub) set_double_attribute Gurobi::GRB_DBL_ATTR_LB, var_index, lb set_double_attribute Gurobi::GRB_DBL_ATTR_UB, var_index, ub end
update()
click to toggle source
Update the model
Calls superclass method
# File lib/mipper/gurobi/model.rb, line 25 def update super ret = Gurobi.GRBupdatemodel @ptr fail if ret != 0 end
write_lp(filename)
click to toggle source
Write the model to a file in CPLEX LP format
# File lib/mipper/gurobi/model.rb, line 33 def write_lp(filename) Gurobi.GRBwrite @ptr, filename end
write_mps(filename)
click to toggle source
Write the model to a file in MPS format
# File lib/mipper/gurobi/model.rb, line 38 def write_mps(filename) Gurobi.GRBwrite @ptr, filename end
Protected Instance Methods
add_constraint(constr)
click to toggle source
Add a new constraint to the model
# File lib/mipper/gurobi/model.rb, line 163 def add_constraint(constr) terms = constr.expression.terms indexes_buffer = build_pointer_array(terms.each_key.map do |var| var.index end, :int) values_buffer = build_pointer_array terms.values, :double ret = Gurobi.GRBaddconstr @ptr, terms.length, indexes_buffer, values_buffer, gurobi_sense(constr.sense), constr.rhs, constr.name fail if ret != 0 constr.model = self constr.index = @constraints.length constr.freeze @constraints << constr end
add_constraints(constrs)
click to toggle source
Add multiple constraints at once
# File lib/mipper/gurobi/model.rb, line 135 def add_constraints(constrs) cbeg, cind, cval = build_constraint_matrix constrs cbeg_buffer = build_pointer_array cbeg, :int cind_buffer = build_pointer_array cind, :int cval_buffer = build_pointer_array cval, :double sense_buffer = build_pointer_array(constrs.map do |c| gurobi_sense(c.sense) end, :char) rhs_buffer = build_pointer_array constrs.map(&:rhs), :double names_buffer = build_pointer_array array_to_pointers_to_names(constrs), :pointer ret = Gurobi.GRBaddconstrs @ptr, constrs.length, cind.length, cbeg_buffer, cind_buffer, cval_buffer, sense_buffer, rhs_buffer, names_buffer fail if ret != 0 constrs.each do |constr| constr.model = self constr.index = @constraints.length constr.freeze @constraints << constr end end
add_variable(var)
click to toggle source
Add a new variable to the model
# File lib/mipper/gurobi/model.rb, line 125 def add_variable(var) ret = Gurobi.GRBaddvar @ptr, 0, nil, nil, var.coefficient, var.lower_bound, var.upper_bound, gurobi_type(var.type), var.name fail if ret != 0 store_variable var end
add_variables(vars)
click to toggle source
Add multiple variables to the model simultaneously
# File lib/mipper/gurobi/model.rb, line 100 def add_variables(vars) objective_buffer = build_pointer_array vars.map(&:coefficient), :double lb_buffer = build_pointer_array vars.map(&:lower_bound), :double ub_buffer = build_pointer_array vars.map(&:upper_bound), :double type_buffer = build_pointer_array(vars.map do |var| gurobi_type(var.type) end, :char) names_buffer = build_pointer_array array_to_pointers_to_names(vars), :pointer ret = Gurobi.GRBaddvars @ptr, vars.length, 0, nil, nil, nil, objective_buffer, lb_buffer, ub_buffer, type_buffer, names_buffer fail if ret != 0 # Store all the variables in the model vars.each { |var| store_variable var } # Update the model with variables so constraint adds succeed ret = Gurobi.GRBupdatemodel @ptr fail if ret != 0 end
gurobi_objective()
click to toggle source
The value of the objective function
# File lib/mipper/gurobi/model.rb, line 92 def gurobi_objective dblptr = FFI::MemoryPointer.new :pointer ret = Gurobi.GRBgetdblattr @ptr, Gurobi::GRB_DBL_ATTR_OBJVAL, dblptr fail if ret != 0 dblptr.read_double end
gurobi_status()
click to toggle source
Get the status of the model
# File lib/mipper/gurobi/model.rb, line 75 def gurobi_status intptr = FFI::MemoryPointer.new :pointer ret = Gurobi.GRBgetintattr @ptr, Gurobi::GRB_INT_ATTR_STATUS, intptr fail if ret != 0 case intptr.read_int when Gurobi::GRB_OPTIMAL :optimized when Gurobi::GRB_INFEASIBLE, Gurobi::GRB_INF_OR_UNBD, Gurobi::GRB_UNBOUNDED :invalid else :unknown end end
Private Instance Methods
array_to_pointers_to_names(arr)
click to toggle source
Convert an array of objects to an FFI array of memory pointers to the names of each object
# File lib/mipper/gurobi/model.rb, line 243 def array_to_pointers_to_names(arr) arr.map do |obj| obj.name.nil? ? nil : FFI::MemoryPointer.from_string(obj.name) end end
build_constraint_matrix(constrs)
click to toggle source
Construct a matrix of values for the given list of constraints
# File lib/mipper/gurobi/model.rb, line 190 def build_constraint_matrix(constrs) cbeg = [] cind = [] cval = [] constrs.each.map do |constr| cbeg << cind.length constr.expression.terms.each do |var, coeff| cind << var.index cval << coeff end end [cbeg, cind, cval] end
gurobi_sense(sense)
click to toggle source
# File lib/mipper/gurobi/model.rb, line 249 def gurobi_sense(sense) sense.to_s[0].ord end
gurobi_type(type)
click to toggle source
# File lib/mipper/gurobi/model.rb, line 253 def gurobi_type(type) case type when :integer Gurobi::GRB_INTEGER.ord when :binary Gurobi::GRB_BINARY.ord when :continuous Gurobi::GRB_CONTINUOUS.ord else fail type end end
save_solution()
click to toggle source
Save the solution to the model for access later
# File lib/mipper/gurobi/model.rb, line 206 def save_solution status = gurobi_status if status == :optimized objective_value = gurobi_objective variable_values = @variables.map do |var| dblptr = FFI::MemoryPointer.new :pointer Gurobi.GRBgetdblattrarray @ptr, Gurobi::GRB_DBL_ATTR_X, var.index, 1, dblptr dblptr.read_array_of_double(1)[0] end else objective_value = nil variable_values = [] end @solution = Solution.new status, objective_value, variable_values end
set_double_attribute(name, var_index, value)
click to toggle source
# File lib/mipper/gurobi/model.rb, line 235 def set_double_attribute(name, var_index, value) buffer = build_pointer_array [value], :double ret = Gurobi.GRBsetdblattrarray @ptr, name, var_index, 1, buffer fail if ret != 0 end
store_variable(var)
click to toggle source
Save the variable to the model and update the variable pointers
# File lib/mipper/gurobi/model.rb, line 226 def store_variable(var) # Update the variable to track the index in the model var.model = self var.index = @var_count @var_count += 1 @variables << var end