Getting started with JuMP

This tutorial is aimed at providing a quick introduction to writing JuMP code. If you're new to Julia, you should start with Getting started with Julia.

What is JuMP?

JuMP ("Julia for Mathematical Programming") is an open-source modeling language that is embedded in Julia. It allows users to users formulate various classes of optimization problems (linear, mixed-integer, quadratic, conic quadratic, semidefinite, and nonlinear) with easy-to-read code. These problems can then be solved using state-of-the-art open-source and commercial solvers.

JuMP also makes advanced optimization techniques easily accessible from a high-level language.

Installation

JuMP is a package for Julia. From Julia, JuMP is installed by using the built-in package manager.

import Pkg
Pkg.add("JuMP")

You also need to include a Julia package which provides an appropriate solver. One such solver is GLPK.Optimizer, which is provided by the GLPK.jl package.

import Pkg
Pkg.add("GLPK")

See Installation Guide for a list of other solvers you can use.

An example

Let's try to solve the following linear programming problem by using JuMP and GLPK. We will first look at the complete code to solve the problem and then go through it step by step.

\[\begin{aligned} & \min & 12x + 20y \\ & \;\;\text{s.t.} & 6x + 8y \geq 100 \\ & & 7x + 12y \geq 120 \\ & & x \geq 0 \\ & & y \in [0, 3] \\ \end{aligned}\]

using JuMP
using GLPK
model = Model(GLPK.Optimizer)
@variable(model, x >= 0)
@variable(model, 0 <= y <= 3)
@objective(model, Min, 12x + 20y)
@constraint(model, c1, 6x + 8y >= 100)
@constraint(model, c2, 7x + 12y >= 120)
print(model)
optimize!(model)
@show termination_status(model)
@show primal_status(model)
@show dual_status(model)
@show objective_value(model)
@show value(x)
@show value(y)
@show shadow_price(c1)
@show shadow_price(c2)
Min 12 x + 20 y
Subject to
 c1 : 6 x + 8 y ≥ 100.0
 c2 : 7 x + 12 y ≥ 120.0
 x ≥ 0.0
 y ≥ 0.0
 y ≤ 3.0
termination_status(model) = OPTIMAL::TerminationStatusCode = 1
primal_status(model) = FEASIBLE_POINT::ResultStatusCode = 1
dual_status(model) = FEASIBLE_POINT::ResultStatusCode = 1
objective_value(model) = 204.99999999999997
value(x) = 15.000000000000005
value(y) = 1.249999999999996
shadow_price(c1) = -0.24999999999999922
shadow_price(c2) = -1.5000000000000007

Step-by-step

Once JuMP is installed, to use JuMP in your programs, we just need to write:

using JuMP

We also need to include a Julia package which provides an appropriate solver. We want to use GLPK.Optimizer here which is provided by the GLPK.jl package.

using GLPK

A model object is a container for variables, constraints, solver options, etc. Models are created with the Model function. The model can be created with an optimizer attached with default arguments by calling the constructor with the optimizer type, as follows:

model = Model(GLPK.Optimizer)
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: EMPTY_OPTIMIZER
Solver name: GLPK

Variables are modeled using @variable:

@variable(model, x >= 0)

\[ x \]

They can have lower and upper bounds.

@variable(model, 0 <= y <= 30)

\[ y \]

The objective is set using @objective:

@objective(model, Min, 12x + 20y)

\[ 12 x + 20 y \]

Constraints are modeled using @constraint. Here c1 and c2 are the names of our constraint.

@constraint(model, c1, 6x + 8y >= 100)

c1 : $ 6 x + 8 y \geq 100.0 $

@constraint(model, c2, 7x + 12y >= 120)

c2 : $ 7 x + 12 y \geq 120.0 $

print(model)
Min 12 x + 20 y
Subject to
 c1 : 6 x + 8 y ≥ 100.0
 c2 : 7 x + 12 y ≥ 120.0
 x ≥ 0.0
 y ≥ 0.0
 y ≤ 30.0

To solve the optimization problem, call the [optimize!] function.

optimize!(model)
Info

The ! after optimize is just part of the name. It's nothing special. Julia has a convention that functions which mutate their arguments should end in !. A common example is push!.

Now let's see what information we can query about the solution.

termination_status tells us why the solver stopped:

termination_status(model)
OPTIMAL::TerminationStatusCode = 1

In this case, the solver found an optimal solution. We should also check primal_status to see if the solver found a primal feasible point:

primal_status(model)
FEASIBLE_POINT::ResultStatusCode = 1

and dual_status to see if the solver found a dual feasible point:

dual_status(model)
FEASIBLE_POINT::ResultStatusCode = 1

Now we know that our solver found an optimal solution, and has a primal and a dual solution to query.

Query the objective value using objective_value:

objective_value(model)
205.0

The primal solution using value:

value(x)
14.999999999999993
value(y)
1.2500000000000047

and the dual solution using shadow_price:

shadow_price(c1)
-0.249999999999999
shadow_price(c2)
-1.5000000000000007

View this file on Github.


This page was generated using Literate.jl.