Title: | Model and Solve Mixed Integer Linear Programs |
---|---|
Description: | Model mixed integer linear programs in an algebraic way directly in R. The model is solver-independent and thus offers the possibility to solve a model with different solvers. It currently only supports linear constraints and objective functions. See the 'ompr' website <https://dirkschumacher.github.io/ompr/> for more information, documentation and examples. |
Authors: | Dirk Schumacher [aut, cre] |
Maintainer: | Dirk Schumacher <[email protected]> |
License: | MIT + file LICENSE |
Version: | 1.0.4.9000 |
Built: | 2024-11-02 02:40:47 UTC |
Source: | https://github.com/dirkschumacher/ompr |
Add one or more constraints to the model using quantifiers.
add_constraint(.model, .constraint_expr, ..., .show_progress_bar = TRUE) add_constraint_( .model, .constraint_expr, ..., .dots, .show_progress_bar = TRUE )
add_constraint(.model, .constraint_expr, ..., .show_progress_bar = TRUE) add_constraint_( .model, .constraint_expr, ..., .dots, .show_progress_bar = TRUE )
.model |
the model |
.constraint_expr |
the constraint. Must be a linear (in)equality with operator "<=", "==" or ">=". |
... |
quantifiers for the indexed variables. For all combinations of bound variables a new constraint is created. In addition you can add filter expressions |
.show_progress_bar |
displays a progressbar when adding multiple constraints |
.dots |
Used to work around non-standard evaluation. |
a Model with new constraints added
library(magrittr) MIPModel() %>% add_variable(x[i], i = 1:5) %>% # creates 5 constraints add_constraint(x[i] >= 1, i = 1:5) %>% # you can also use filter expressions add_constraint(x[i] >= 1, i = 1:5, i %% 2 == 0) %>% # and depent on other indexes add_constraint(x[j] >= 1, i = 1:10, j = 1:i, j <= 5)
library(magrittr) MIPModel() %>% add_variable(x[i], i = 1:5) %>% # creates 5 constraints add_constraint(x[i] >= 1, i = 1:5) %>% # you can also use filter expressions add_constraint(x[i] >= 1, i = 1:5, i %% 2 == 0) %>% # and depent on other indexes add_constraint(x[j] >= 1, i = 1:10, j = 1:i, j <= 5)
A variable can either be a name or an indexed name. See examples.
add_variable(.model, .variable, ..., type = "continuous", lb = -Inf, ub = Inf) add_variable_( .model, .variable, ..., type = "continuous", lb = -Inf, ub = Inf, .dots )
add_variable(.model, .variable, ..., type = "continuous", lb = -Inf, ub = Inf) add_variable_( .model, .variable, ..., type = "continuous", lb = -Inf, ub = Inf, .dots )
.model |
the model |
.variable |
the variable name/definition |
... |
quantifiers for the indexed variable. Including filters |
type |
must be either continuous, integer or binary |
lb |
the lower bound of the variable |
ub |
the upper bound of the variable |
.dots |
Used to work around non-standard evaluation. |
library(magrittr) MIPModel() %>% add_variable(x) %>% # creates 1 variable named x add_variable(y[i], i = 1:10, i %% 2 == 0, type = "binary" ) # creates 4 variables
library(magrittr) MIPModel() %>% add_variable(x) %>% # creates 1 variable named x add_variable(y[i], i = 1:10, i %% 2 == 0, type = "binary" ) # creates 4 variables
Retrieve additional solver specific output
additional_solver_output(solution)
additional_solver_output(solution)
solution |
a solution object |
A list of named entries. What is in that list is determined
by the solver function. For ompr.roi
this is usually a solver specific
message and status information.
Convert lists or vectors to colwise semantic.
as_colwise(x)
as_colwise(x)
x |
a list of numeric vectors or a numeric vector |
This function should be used if you to expand a variable across columns and not rows. When passing a vector of indexes to MILPModel variable, it creates a new row for each vector element. With colwise you can create columns instead. Please see the examples below.
colwise(...)
colwise(...)
... |
create a colwise vector |
'colwise' is probably the concept that is likely to change in the future.
## Not run: # vectors create matrix rows # x[1, 1] # x[2, 1] # x[3, 1] x[1:3, 1] # colwise() creates columns per row # 1 * x[1, 1] + 2 * x[1, 2] + 3 * x[1, 3] colwise(1, 2, 3) * x[1, colwise(1, 2, 3)] # or you have multiple rows and columns and different coefficients # 1 * x[1, 1] + 2 * x[1, 2] + 3 * x[1, 3] # 4 * x[2, 1] + 5 * x[2, 2] + 6 * x[1, 3] colwise(1:6) * x[1:2, colwise(1:3)] # in the example above, the colwise vector multiplied with the variable # has an element per row and column # in general, it can be a multiple of number of columns # you can also combine the two # x[1, 1] # x[2, 1] + x[2, 2] # x[3, 1] + x[3, 2] + x[3, 2] x[1:3, colwise(1, 1:2, 1:3)] ## End(Not run)
## Not run: # vectors create matrix rows # x[1, 1] # x[2, 1] # x[3, 1] x[1:3, 1] # colwise() creates columns per row # 1 * x[1, 1] + 2 * x[1, 2] + 3 * x[1, 3] colwise(1, 2, 3) * x[1, colwise(1, 2, 3)] # or you have multiple rows and columns and different coefficients # 1 * x[1, 1] + 2 * x[1, 2] + 3 * x[1, 3] # 4 * x[2, 1] + 5 * x[2, 2] + 6 * x[1, 3] colwise(1:6) * x[1:2, colwise(1:3)] # in the example above, the colwise vector multiplied with the variable # has an element per row and column # in general, it can be a multiple of number of columns # you can also combine the two # x[1, 1] # x[2, 1] + x[2, 2] # x[3, 1] + x[3, 2] + x[3, 2] x[1:3, colwise(1, 1:2, 1:3)] ## End(Not run)
Extract the constraint matrix, the right hand side and the sense from a model
extract_constraints(model)
extract_constraints(model)
model |
the model |
a list with three named elements. 'matrix' the (sparse) constraint matrix from the Matrix package. 'rhs' is the right hand side vector in the order of the matrix. 'sense' is a vector of the constraint senses
library(magrittr) model <- MIPModel() %>% add_variable(x[i], i = 1:3) %>% add_variable(y[i], i = 1:3) %>% add_constraint(x[i] + y[i] <= 1, i = 1:3) extract_constraints(model)
library(magrittr) model <- MIPModel() %>% add_variable(x[i], i = 1:3) %>% add_variable(y[i], i = 1:3) %>% add_constraint(x[i] + y[i] <= 1, i = 1:3) extract_constraints(model)
Gets the column duals of a solution
get_column_duals(solution)
get_column_duals(solution)
solution |
a solution |
Either a numeric vector with one element per column or 'NA_real_'.
## Not run: result <- MIPModel() %>% add_variable(x[i], i = 1:5) %>% add_variable(y[i, j], i = 1:5, j = 1:5) %>% add_constraint(x[i] >= 1, i = 1:5) %>% set_bounds(x[i], lb = 3, i = 1:3) %>% set_objective(sum_over(i * x[i], i = 1:5)) %>% solve_model(with_ROI("glpk")) get_column_duals(result) ## End(Not run)
## Not run: result <- MIPModel() %>% add_variable(x[i], i = 1:5) %>% add_variable(y[i, j], i = 1:5, j = 1:5) %>% add_constraint(x[i] >= 1, i = 1:5) %>% set_bounds(x[i], lb = 3, i = 1:3) %>% set_objective(sum_over(i * x[i], i = 1:5)) %>% solve_model(with_ROI("glpk")) get_column_duals(result) ## End(Not run)
Gets the row duals of a solution
get_row_duals(solution)
get_row_duals(solution)
solution |
a solution |
Either a numeric vector with one element per row or 'NA_real_'.
## Not run: result <- MIPModel() %>% add_variable(x[i], i = 1:5) %>% add_variable(y[i, j], i = 1:5, j = 1:5) %>% add_constraint(x[i] >= 1, i = 1:5) %>% set_bounds(x[i], lb = 3, i = 1:3) %>% set_objective(sum_expr(i * x[i], i = 1:5)) %>% solve_model(with_ROI("glpk")) get_row_duals(result) ## End(Not run)
## Not run: result <- MIPModel() %>% add_variable(x[i], i = 1:5) %>% add_variable(y[i, j], i = 1:5, j = 1:5) %>% add_constraint(x[i] >= 1, i = 1:5) %>% set_bounds(x[i], lb = 3, i = 1:3) %>% set_objective(sum_expr(i * x[i], i = 1:5)) %>% solve_model(with_ROI("glpk")) get_row_duals(result) ## End(Not run)
Get variable values from a solution
get_solution(solution, expr, type = "primal") get_solution_(solution, expr, type = "primal")
get_solution(solution, expr, type = "primal") get_solution_(solution, expr, type = "primal")
solution |
the solution object |
expr |
a variable expression. You can partially bind indexes. |
type |
optional, either "primal" or "dual". The default value is "primal". If "primal" it returns the primal solution, otherwise the column duals. Especially the dual values depend on the solver. If no duals are calculated, the function stops with an error message. |
a data.frame. One row for each variable instance
and a column for each index.
Unless it is a single variable, then it returns a single number.
Please note that in case of a data.frame
there is no
guarantee about the ordering of the rows. This could change
in future ompr
versions. Please always use the indexes
to retrieve the correct values.
## Not run: library(magrittr) result <- MIPModel() %>% add_variable(x[i], i = 1:5) %>% add_variable(y[i, j], i = 1:5, j = 1:5) %>% add_constraint(x[i] >= 1, i = 1:5) %>% set_bounds(x[i], lb = 3, i = 1:3) %>% set_objective(0) %>% solve_model(with_ROI("glpk")) solution <- get_solution(result, x[i]) solution2 <- get_solution(result, y[i, 1]) solution3 <- get_solution(result, y[i, j]) duals <- get_solution(result, x[i], type = "dual") ## End(Not run)
## Not run: library(magrittr) result <- MIPModel() %>% add_variable(x[i], i = 1:5) %>% add_variable(y[i, j], i = 1:5, j = 1:5) %>% add_constraint(x[i] >= 1, i = 1:5) %>% set_bounds(x[i], lb = 3, i = 1:3) %>% set_objective(0) %>% solve_model(with_ROI("glpk")) solution <- get_solution(result, x[i]) solution2 <- get_solution(result, y[i, 1]) solution3 <- get_solution(result, y[i, j]) duals <- get_solution(result, x[i], type = "dual") ## End(Not run)
Create an an empty mixed-integer linear programming model that is about 1000 times faster than 'MIPModel'.
MILPModel()
MILPModel()
Please only use it if you can deal with potential API changes in the future. When you use 'MILPModel' make sure to always model your problem with 'MIPModel' as well, just to make sure you get the same results.
It is also always a good idea to test your model with very small input sizes and examine the coefficients and rows of the constraint matrix.
Number of variables (rows) of the model
nconstraints(model)
nconstraints(model)
model |
the model |
An integer equal to the number of variables. A variable is here a column in the resulting constraint matrix.
library(magrittr) model <- MIPModel() %>% add_variable(x) %>% add_variable(y[i], i = 1:10) nconstraints(model) # 11
library(magrittr) model <- MIPModel() %>% add_variable(x) %>% add_variable(y[i], i = 1:10) nconstraints(model) # 11
This function/class should only be used if you develop your own solver.
new_solution( model, objective_value, status, solution, solution_column_duals = function() NA_real_, solution_row_duals = function() NA_real_, additional_solver_output = list() )
new_solution( model, objective_value, status, solution, solution_column_duals = function() NA_real_, solution_row_duals = function() NA_real_, additional_solver_output = list() )
model |
the optimization model that was solved |
objective_value |
a numeric objective value |
status |
the status of the solution |
solution |
a named numeric vector containing the primal solution values |
solution_column_duals |
A function without arguments that returns a numeric vector containing the column dual solution values. 'NA_real_', if no column duals are available/defined. |
solution_row_duals |
A function without arguments that returns a numeric vector containing the column dual solution values. 'NA_real_', if no column duals are available/defined. |
additional_solver_output |
A named list of additional solver information |
Number of variables of a model
nvars(model)
nvars(model)
model |
the model |
a list with three named elements. 'binary' => number of binary variables, 'integer' => number of integer variables, 'continuous' => number of continuous variables.
library(magrittr) model <- MIPModel() %>% add_variable(x[i], i = 1:10, type = "binary") %>% add_variable(y[i], i = 1:5, type = "continuous") %>% add_variable(z[i], i = 1:2, type = "integer") nvars(model)
library(magrittr) model <- MIPModel() %>% add_variable(x[i], i = 1:10, type = "binary") %>% add_variable(y[i], i = 1:5, type = "continuous") %>% add_variable(z[i], i = 1:2, type = "integer") nvars(model)
Extract the objective function from a model
objective_function(model)
objective_function(model)
model |
the model |
a list with two named elements, 'solution' and 'constant'. 'solution' is a sparse vector from the Matrix package. 'constant' is a constant that needs to be added to get the final obj. value.
library(magrittr) model <- MIPModel() %>% add_variable(x[i], i = 1:5) %>% set_objective(sum_over(i * x[i], i = 1:5) + 10) objective_function(model)
library(magrittr) model <- MIPModel() %>% add_variable(x[i], i = 1:5) %>% set_objective(sum_over(i * x[i], i = 1:5) + 10) objective_function(model)
Extract the numerical objective value from a solution
objective_value(solution)
objective_value(solution)
solution |
a solution |
numeric single item vector
Change the lower and upper bounds of a named variable, indexed variable or a group of variables.
set_bounds(.model, .variable, ..., lb = NULL, ub = NULL) set_bounds_(.model, .variable, ..., lb = NULL, ub = NULL, .dots)
set_bounds(.model, .variable, ..., lb = NULL, ub = NULL) set_bounds_(.model, .variable, ..., lb = NULL, ub = NULL, .dots)
.model |
the model |
.variable |
the variable name/definition or a linear constraint |
... |
quantifiers for the indexed variable |
lb |
the lower bound of the variable. |
ub |
the upper bound of the variable For |
.dots |
Used to work around non-standard evaluation. |
library(magrittr) MIPModel() %>% add_variable(x[i], i = 1:5) %>% add_constraint(x[i] >= 1, i = 1:5) %>% # creates 5 constraints set_bounds(x[i], lb = 3, i = 1:3) %>% variable_bounds() MIPModel() %>% add_variable(x[i], i = 1:5) %>% set_bounds(x[i] <= i, i = 1:5) %>% # upper bound set_bounds(x[i] >= 0, i = 1:5) %>% # lower bound set_bounds(x[5] == 45) %>% variable_bounds()
library(magrittr) MIPModel() %>% add_variable(x[i], i = 1:5) %>% add_constraint(x[i] >= 1, i = 1:5) %>% # creates 5 constraints set_bounds(x[i], lb = 3, i = 1:3) %>% variable_bounds() MIPModel() %>% add_variable(x[i], i = 1:5) %>% set_bounds(x[i] <= i, i = 1:5) %>% # upper bound set_bounds(x[i] >= 0, i = 1:5) %>% # lower bound set_bounds(x[5] == 45) %>% variable_bounds()
Set the model objective
set_objective(model, expression, sense = c("max", "min")) set_objective_(model, expression, sense = c("max", "min"))
set_objective(model, expression, sense = c("max", "min")) set_objective_(model, expression, sense = c("max", "min"))
model |
the model |
expression |
the linear objective as a sum of variables and constants |
sense |
the model sense. Must be either "max" or "min". |
a Model with a new objective function definition
library(magrittr) MIPModel() %>% add_variable(x, lb = 2) %>% add_variable(y, lb = 40) %>% set_objective(x + y, sense = "min")
library(magrittr) MIPModel() %>% add_variable(x, lb = 2) %>% add_variable(y, lb = 40) %>% set_objective(x + y, sense = "min")
Solve a model
solve_model(model, solver)
solve_model(model, solver)
model |
the model |
solver |
a function mapping a model to a solution |
solver(model)
Get the solver status from a solution
solver_status(solution)
solver_status(solution)
solution |
a solution |
character vector being either "infeasible", "optimal", "unbounded", "userlimit" or "error
This functions helps to create summations over indexes.
sum_over(.expr, ...) sum_expr(.expr, ...)
sum_over(.expr, ...) sum_expr(.expr, ...)
.expr |
an expression that can be expanded to a sum |
... |
bind variables in expr using dots. See examples. |
the sum over all the indexes
Please note that sum_expr
is deprecated when used together with
MIPModel
.
if (FALSE) { # create a sum from x_1 to x_10 sum_over(x[i], i = 1:10) # create a sum from x_2 to x_10 with even indexes sum_over(x[i], i = 1:10, i %% 2 == 0) sum_over(x[i, j], i = 1:10, j = 1:i) }
if (FALSE) { # create a sum from x_1 to x_10 sum_over(x[i], i = 1:10) # create a sum from x_2 to x_10 with even indexes sum_over(x[i], i = 1:10, i %% 2 == 0) sum_over(x[i, j], i = 1:10, j = 1:i) }
Variable lower and upper bounds of a model
variable_bounds(model)
variable_bounds(model)
model |
the model |
a list with two components 'lower' and 'upper' each having a numeric vector of bounds. One for each variable.
library(magrittr) model <- MIPModel() %>% add_variable(x, type = "binary") %>% add_variable(y, type = "continuous", lb = 2) %>% add_variable(z, type = "integer", ub = 3) variable_bounds(model)
library(magrittr) model <- MIPModel() %>% add_variable(x, type = "binary") %>% add_variable(y, type = "continuous", lb = 2) %>% add_variable(z, type = "integer", ub = 3) variable_bounds(model)
Get all unique names of the model variables
variable_keys(model)
variable_keys(model)
model |
the model |
a character vector ordered in the same way as the constraint matrix columns and objective vector
library(magrittr) model <- MIPModel() %>% add_variable(x[i], i = 1:3) variable_keys(model)
library(magrittr) model <- MIPModel() %>% add_variable(x[i], i = 1:3) variable_keys(model)
One component for each variable in the correct order
variable_types(model)
variable_types(model)
model |
the model |
a factor with levels binary, continuous, integer
library(magrittr) model <- MIPModel() %>% add_variable(x, type = "binary") %>% add_variable(y, type = "continuous") %>% add_variable(z, type = "integer") variable_types(model)
library(magrittr) model <- MIPModel() %>% add_variable(x, type = "binary") %>% add_variable(y, type = "continuous") %>% add_variable(z, type = "integer") variable_types(model)