Class: LpSolver::Model
- Inherits:
-
Object
- Object
- LpSolver::Model
- Defined in:
- lib/lpsolver/model.rb
Overview
A high-level interface to HiGHS for building and solving LP/QP/MIP models.
The Model class provides a Ruby DSL for defining variables, constraints, and objectives. Models are solved via a pluggable driver.
Instance Attribute Summary collapse
-
#constraints_data ⇒ Hash{Symbol => Hash}
readonly
Maps constraint names to their data.
-
#driver ⇒ Drivers::CliDriver, Drivers::NativeDriver
The configured solver driver.
-
#heading ⇒ Symbol
readonly
The current optimization heading.
-
#name ⇒ String
readonly
The model name.
-
#objective ⇒ Hash{Integer => Float}
readonly
Maps variable indices to coefficients.
-
#quadratic_terms ⇒ Array<[Integer, Integer, Float]>
readonly
Quadratic term entries.
-
#var_bounds ⇒ Hash{Symbol => Array<Float>}
readonly
Maps variable names to [lb, ub] bounds.
-
#var_counter ⇒ Integer
readonly
The next available variable index.
-
#var_types ⇒ Hash{Symbol => Symbol}
readonly
Maps variable names to their types.
-
#variables ⇒ Hash{Symbol => Variable}
readonly
All variables defined in this model.
Class Method Summary collapse
-
.default_driver ⇒ Drivers::CliDriver, Drivers::NativeDriver
Returns the default solver driver.
Instance Method Summary collapse
-
#add_constraint(name, expr, lb: -Float::INFINITY,, ub: Float::INFINITY) ⇒ Symbol
Adds a constraint to the model.
-
#add_variable(name, lb: 0.0, ub: Float::INFINITY, integer: false) ⇒ Variable
Adds a variable to the model.
-
#constraints ⇒ Array<Hash>
Constraint data as an array of lb, ub, expr.
-
#initialize(name = nil) ⇒ Model
constructor
Creates a new empty LP/QP/MIP model.
-
#maximize!(objective) ⇒ Solution
Sets heading to maximize, sets the objective, and solves.
-
#minimize!(objective) ⇒ Solution
Sets heading to minimize, sets the objective, and solves.
-
#solve ⇒ Solution
Solves the model using the configured driver, with automatic fallback.
-
#to_lp ⇒ String
Converts the model to HiGHS LP format string.
-
#write_lp(filename) ⇒ void
Writes the model to an LP file.
Constructor Details
#initialize(name = nil) ⇒ Model
Creates a new empty LP/QP/MIP model.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/lpsolver/model.rb', line 85 def initialize(name = nil) @name = name || 'untitled' @variables = {} # { symbol => Variable } @constraints = {} # { symbol => index } @var_counter = 0 @constr_counter = 0 @heading = :minimize @solution = nil @objective = {} # { var_index => coefficient } @quadratic_terms = [] # [[var1_idx, var2_idx, coefficient], ...] @var_types = {} # { symbol => :continuous | :integer } @var_bounds = {} # { symbol => [lb, ub] } @constraints_data = {} # { symbol => { lb:, ub:, expr: [[var_idx, coeff], ...] } } @driver = self.class.default_driver end |
Instance Attribute Details
#constraints_data ⇒ Hash{Symbol => Hash} (readonly)
Returns Maps constraint names to their data.
21 22 23 |
# File 'lib/lpsolver/model.rb', line 21 def constraints_data @constraints_data end |
#driver ⇒ Drivers::CliDriver, Drivers::NativeDriver
Returns The configured solver driver.
33 34 35 |
# File 'lib/lpsolver/model.rb', line 33 def driver @driver end |
#heading ⇒ Symbol (readonly)
Returns The current optimization heading.
15 16 17 |
# File 'lib/lpsolver/model.rb', line 15 def heading @heading end |
#name ⇒ String (readonly)
Returns The model name.
31 32 33 |
# File 'lib/lpsolver/model.rb', line 31 def name @name end |
#objective ⇒ Hash{Integer => Float} (readonly)
Returns Maps variable indices to coefficients.
25 26 27 |
# File 'lib/lpsolver/model.rb', line 25 def objective @objective end |
#quadratic_terms ⇒ Array<[Integer, Integer, Float]> (readonly)
Returns Quadratic term entries.
27 28 29 |
# File 'lib/lpsolver/model.rb', line 27 def quadratic_terms @quadratic_terms end |
#var_bounds ⇒ Hash{Symbol => Array<Float>} (readonly)
Returns Maps variable names to [lb, ub] bounds.
29 30 31 |
# File 'lib/lpsolver/model.rb', line 29 def var_bounds @var_bounds end |
#var_counter ⇒ Integer (readonly)
Returns The next available variable index.
13 14 15 |
# File 'lib/lpsolver/model.rb', line 13 def var_counter @var_counter end |
#var_types ⇒ Hash{Symbol => Symbol} (readonly)
Returns Maps variable names to their types.
23 24 25 |
# File 'lib/lpsolver/model.rb', line 23 def var_types @var_types end |
#variables ⇒ Hash{Symbol => Variable} (readonly)
Returns All variables defined in this model.
11 12 13 |
# File 'lib/lpsolver/model.rb', line 11 def variables @variables end |
Class Method Details
.default_driver ⇒ Drivers::CliDriver, Drivers::NativeDriver
Returns the default solver driver.
Tries CliDriver first (if HiGHS binary is available), then falls back to NativeDriver (if native extension is compiled), then raises an error.
42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/lpsolver/model.rb', line 42 def self.default_driver begin Drivers::CliDriver.new rescue begin Drivers::NativeDriver.new rescue LoadError raise 'No solver available. Install HiGHS or compile the native extension with: rake compile' end end end |
Instance Method Details
#add_constraint(name, expr, lb: -Float::INFINITY,, ub: Float::INFINITY) ⇒ Symbol
Adds a constraint to the model.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/lpsolver/model.rb', line 127 def add_constraint(name, expr, lb: -Float::INFINITY, ub: Float::INFINITY) name = name.to_sym if expr.is_a?(ConstraintSpec) lb_val, ub_val = expr.bounds data_expr = expr.expr else lb_val = lb ub_val = ub data_expr = expr end idx = @constr_counter @constraints[name] = idx @constraints_data[name] = { lb: normalize_bound(lb_val), ub: normalize_bound(ub_val), expr: data_expr } @constr_counter += 1 name end |
#add_variable(name, lb: 0.0, ub: Float::INFINITY, integer: false) ⇒ Variable
Adds a variable to the model.
108 109 110 111 112 113 114 115 116 117 |
# File 'lib/lpsolver/model.rb', line 108 def add_variable(name, lb: 0.0, ub: Float::INFINITY, integer: false) name = name.to_sym idx = @var_counter var = Variable.new(idx, name) @variables[name] = var @var_types[name] = integer ? :integer : :continuous @var_bounds[name] = [normalize_bound(lb), normalize_bound(ub)] @var_counter += 1 var end |
#constraints ⇒ Array<Hash>
Returns Constraint data as an array of lb, ub, expr.
17 18 19 |
# File 'lib/lpsolver/model.rb', line 17 def constraints @constraints_data.values end |
#maximize!(objective) ⇒ Solution
Sets heading to maximize, sets the objective, and solves.
166 167 168 169 170 |
# File 'lib/lpsolver/model.rb', line 166 def maximize!(objective) @heading = :maximize set_objective_internal(objective) solve end |
#minimize!(objective) ⇒ Solution
Sets heading to minimize, sets the objective, and solves.
155 156 157 158 159 |
# File 'lib/lpsolver/model.rb', line 155 def minimize!(objective) @heading = :minimize set_objective_internal(objective) solve end |
#solve ⇒ Solution
Solves the model using the configured driver, with automatic fallback.
If the configured driver is CliDriver and the HiGHS binary is not found, automatically falls back to NativeDriver. If NativeDriver is also not available, raises the original error.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/lpsolver/model.rb', line 63 def solve begin @driver.solve(self) rescue SolverError, LoadError => e # If CLI driver fails and native driver is available, try it if @driver.class.name.end_with?('CliDriver') begin @driver = Drivers::NativeDriver.new @driver.solve(self) rescue LoadError raise e end else raise e end end end |
#to_lp ⇒ String
Converts the model to HiGHS LP format string.
Delegates to LpGenerator for serialization.
208 209 210 |
# File 'lib/lpsolver/model.rb', line 208 def to_lp LpGenerator.new(self).generate end |
#write_lp(filename) ⇒ void
This method returns an undefined value.
Writes the model to an LP file.
218 219 220 |
# File 'lib/lpsolver/model.rb', line 218 def write_lp(filename) File.write(filename, to_lp) end |