Code Monkey home page Code Monkey logo

ompr's Introduction

Mixed integer linear programming in R

R build status CRAN Status Codecov test coverage

OMPR (Optimization Modeling Package) is a DSL to model and solve Mixed Integer Linear Programs. It is inspired by the excellent Jump project in Julia.

Here are some problems you could solve with this package:

  • What is the cost minimal way to visit a set of clients and return home afterwards?
  • What is the optimal conference time table subject to certain constraints (e.g. availability of a projector)?
  • Sudokus

The Wikipedia article gives a good starting point if you would like to learn more about the topic.

I am always happy to get bug reports or feedback.

Install

CRAN

install.packages("ompr")
install.packages("ompr.roi")

Development version

To install the current development version use devtools:

remotes::install_github("dirkschumacher/ompr")
remotes::install_github("dirkschumacher/ompr.roi")

Available solver bindings

  • ompr.roi - Bindings to ROI (GLPK, Symphony, CPLEX etc.)

A simple example:

suppressPackageStartupMessages(library(dplyr, quietly = TRUE)) 
suppressPackageStartupMessages(library(ROI))
library(ROI.plugin.glpk)
library(ompr)
library(ompr.roi)

result <- MIPModel() |>
  add_variable(x, type = "integer") |>
  add_variable(y, type = "continuous", lb = 0) |>
  set_bounds(x, lb = 0) |>
  set_objective(x + y, "max") |>
  add_constraint(x + y <= 11.25) |>
  solve_model(with_ROI(solver = "glpk"))
get_solution(result, x)
#>  x 
#> 11
get_solution(result, y)
#>    y 
#> 0.25

API

These functions currently form the public API. More detailed docs can be found in the package function docs or on the website

DSL

  • MIPModel() create an empty mixed integer linear model (the old way)
  • add_variable() adds variables to a model
  • set_objective() sets the objective function of a model
  • set_bounds() sets bounds of variables
  • add_constraint() add constraints
  • solve_model() solves a model with a given solver
  • get_solution() returns the column solution (primal or dual) of a solved model for a given variable or group of variables
  • get_row_duals() returns the row duals of a solution (only if it is an LP)
  • get_column_duals() returns the column duals of a solution (only if it is an LP)

Backends

There are currently two backends. A backend is the function that initializes an empty model.

  • MIPModel() is the standard MILP Model.
  • MILPModel() is another backend specifically optimized for linear models and is often faster than MIPModel(). It has different semantics, as it is vectorized. Currently experimental and might be deprecated in the future.

Solvers

Solvers are in different packages. ompr.ROI uses the ROI package which offers support for all kinds of solvers.

  • with_ROI(solver = "glpk") solve the model with GLPK. Install ROI.plugin.glpk
  • with_ROI(solver = "symphony") solve the model with Symphony. Install ROI.plugin.symphony
  • with_ROI(solver = "cplex") solve the model with CPLEX. Install ROI.plugin.cplex
  • … See the ROI package for more plugins.

Further Examples

Please take a look at the docs for bigger examples.

Knapsack

max_capacity <- 5
n <- 10
set.seed(1234)
weights <- runif(n, max = max_capacity)
MIPModel() |>
  add_variable(x[i], i = 1:n, type = "binary") |>
  set_objective(sum_over(weights[i] * x[i], i = 1:n), "max") |>
  add_constraint(sum_over(weights[i] * x[i], i = 1:n) <= max_capacity) |>
  solve_model(with_ROI(solver = "glpk")) |>
  get_solution(x[i]) |>
  filter(value > 0)
#>   variable i value
#> 1        x 1     1
#> 2        x 6     1
#> 3        x 7     1
#> 4        x 8     1

Bin Packing

An example of a more difficult model solved by GLPK

max_bins <- 10
bin_size <- 3
n <- 10
weights <- runif(n, max = bin_size)
MIPModel() |>
  add_variable(y[i], i = 1:max_bins, type = "binary") |>
  add_variable(x[i, j], i = 1:max_bins, j = 1:n, type = "binary") |>
  set_objective(sum_over(y[i], i = 1:max_bins), "min") |>
  add_constraint(sum_over(weights[j] * x[i, j], j = 1:n) <= y[i] * bin_size, i = 1:max_bins) |>
  add_constraint(sum_over(x[i, j], i = 1:max_bins) == 1, j = 1:n) |>
  solve_model(with_ROI(solver = "glpk", verbose = TRUE)) |>
  get_solution(x[i, j]) |>
  filter(value > 0) |>
  arrange(i)
#> <SOLVER MSG>  ----
#> GLPK Simplex Optimizer, v4.65
#> 20 rows, 110 columns, 210 non-zeros
#>       0: obj =   0.000000000e+00 inf =   1.000e+01 (10)
#>      29: obj =   4.546337429e+00 inf =   0.000e+00 (0)
#> *    34: obj =   4.546337429e+00 inf =   0.000e+00 (0)
#> OPTIMAL LP SOLUTION FOUND
#> GLPK Integer Optimizer, v4.65
#> 20 rows, 110 columns, 210 non-zeros
#> 110 integer variables, all of which are binary
#> Integer optimization begins...
#> Long-step dual simplex will be used
#> +    34: mip =     not found yet >=              -inf        (1; 0)
#> +    62: >>>>>   5.000000000e+00 >=   5.000000000e+00   0.0% (13; 0)
#> +    62: mip =   5.000000000e+00 >=     tree is empty   0.0% (0; 25)
#> INTEGER OPTIMAL SOLUTION FOUND
#> <!SOLVER MSG> ----
#>    variable  i  j value
#> 1         x  1  2     1
#> 2         x  1  9     1
#> 3         x  1 10     1
#> 4         x  2  5     1
#> 5         x  2  7     1
#> 6         x  2  8     1
#> 7         x  3  6     1
#> 8         x  4  4     1
#> 9         x 10  1     1
#> 10        x 10  3     1

License

MIT

Contributing

Please post an issue first before sending a PR.

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

Related Projects

  • CVXR - an excellent package for “object-oriented modeling language for convex optimization”. LP/MIP is a special case.
  • ROML follows a similar approach, but it seems the package is still under initial development.

ompr's People

Contributors

dirkschumacher avatar gitter-badger avatar hugolarzabal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ompr's Issues

Bug: -x instead of -1 * x causes problem

add_variable(new("Model"), x, type = "continuous", lb = 4) %>%
    add_variable(y, type = "continuous", ub = 4) %>%
    add_constraint(x + y, "<=", 10) %>%
    set_objective(-x + y, direction = "max") %>%
    solve_model(configure_glpk_solver())

Bug: in solver if registered variables are not used

N <- 10
model <- MIPModel() %>% 
  add_variable(x[i], lb = 0, i = 1:N) %>% 
  add_variable(y[i], lb = 0, i = 1:N) %>% 
  add_variable(a[i, j, s], type = "binary", i = 1:N, j = 1:N, s = 1:3) %>% 
  set_objective(0) %>% 
  add_constraint(x[1] <= 1) 
solve_model(model, with_ROI("glpk"))
in ROI::V_bound(li = li, ui = ui, lb = lb, ub = ub, nobj = max(length(li),  : 
  indices must not exceed number of objective coefficients.

Introduce variablesgroups

Variable groups are sets of single variables that all share the same name but are indexed differently.

Currently a variable can either be a single variable like x or an indexed variable x[1, 3]. A bit messy internally.

You can overwrite model vars

If variables are defined in the calling environment that have the same name as model vars problems will be seen :)

E.g. with extract_coefficients

Remove recursion

Leads to problems with bigger models

max_capacity <- 5
n <- 400
weights <- runif(n, max = max_capacity)
MIPModel() %>%
  add_variable(x[i], i = 1:n, type = "binary") %>%
  set_objective(sum_exp(weights[i] * x[i], i = 1:n), "max") %>%
  add_constraint(sum_exp(weights[i] * x[i], i = 1:n), "<=", max_capacity) %>%
  solve_model(with_ROI(solver = "glpk", verbose = TRUE)) %>% 
  get_solution(x[i]) %>% 
  dplyr::filter(value > 0) 

Standard evaluation version of functions

Standard evaluation is often better for when you want to include code in your own packages. Do you plan to include standard evaluation versions of the functions?

I'm thinking of the dplyr style, for example filter vs. filter_. So you could include add_variable_, set_obejctive_, etc.

I think that most of the logic is handled by the lazyeval package, so it shouldn't be too tricky to implement.

Undocumented blabla

3 Warnings in R CHECK:

* checking whether package 'ompr' can be installed ... WARNING
Found the following significant warnings:
  Warning: undefined slot classes in definition of "Model": objective(class "ObjectiveFunction")

checking for missing documentation entries ... WARNING
Undocumented code objects:
  'add_constraint' 'extract_coefficients' 'get_solution' 'is_defined'
  'solve_model' 'sum_exp'
Undocumented S4 classes:
  'Constraint'
Undocumented S4 methods:
  generic 'add_constraint' and siglist 'Model'
  generic 'add_variable' and siglist 'Model'
  generic 'get_solution' and siglist 'Solution'
  generic 'is_defined' and siglist 'Model'
  generic 'set_objective' and siglist 'Model'
  generic 'show' and siglist 'Model'
  generic 'show' and siglist 'Solution'
  generic 'solve_model' and siglist 'Model,function'
All user-level objects in a package (including S4 classes and methods)
should have documentation entries.
See chapter 'Writing R documentation files' in the 'Writing R
Extensions' manual.
* checking for code/documentation mismatches ... WARNING
S4 class codoc mismatches from documentation object 'Variable-class':
Slots for class 'Variable'
  Code: arity instances lb type ub variable_expression
        variable_quantifiers
  Docs: arity lb type ub

add link to Wikipedia/anything simple

at the beginning of the README for the users that don't know what optimization is. You could also write what problems your package can solve, i.e. a few examples.

Later in the README you could mention which packages in R offer optimization and why yours is better.

ompr.roi produces warning with simple model and set_bounds

MIPModel() %>%
  add_variable(x, type = "integer") %>%
  add_variable(y, type = "continuous", lb = 0) %>%
  set_bounds(x, lb = 0) %>%
  set_objective(x + y, "max") %>%
  add_constraint(x + y <= 11.25) %>%
  solve_model(with_ROI(solver = "glpk")) 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.