Skip to content

Commit e21d29a

Browse files
committed
WIP: [docs] start a tutorial on debugging JuMP models
1 parent a390555 commit e21d29a

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

docs/make.jl

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ const _PAGES = [
105105
"tutorials/getting_started/getting_started_with_sets_and_indexing.md",
106106
"tutorials/getting_started/getting_started_with_data_and_plotting.md",
107107
"tutorials/getting_started/performance_tips.md",
108+
"tutorials/getting_started/debugging.md",
108109
"tutorials/getting_started/design_patterns_for_larger_models.md",
109110
],
110111
"Linear programs" => [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Copyright (c) 2021 Oscar Dowson and contributors #src
2+
# #src
3+
# Permission is hereby granted, free of charge, to any person obtaining a copy #src
4+
# of this software and associated documentation files (the "Software"), to deal #src
5+
# in the Software without restriction, including without limitation the rights #src
6+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell #src
7+
# copies of the Software, and to permit persons to whom the Software is #src
8+
# furnished to do so, subject to the following conditions: #src
9+
# #src
10+
# The above copyright notice and this permission notice shall be included in all #src
11+
# copies or substantial portions of the Software. #src
12+
# #src
13+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #src
14+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #src
15+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #src
16+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #src
17+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #src
18+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #src
19+
# SOFTWARE. #src
20+
21+
# # Debugging
22+
23+
# Dealing with bugs is an unavoidable part of coding optimization models in
24+
# JuMP. This includes bugs related to general Julia code such as syntax errors,
25+
# method errors, typos, and off-by-one indexing errors, but it also includes
26+
# optimization-specific bugs related to the formulation and solution of your
27+
# model.
28+
29+
# This tutorial explains some common sources of bugs and modeling issues that
30+
# you might encounter when writing models in JuMP, and it suggests a variety of
31+
# strategies to deal with them.
32+
33+
# !!! tip
34+
# This tutorial is more advanced than the other "Getting started" tutorials.
35+
# It's in the "Getting started" section to give you an early preview of how
36+
# to test and debug JuMP models. However, if you are new to JuMP, you may
37+
# want to briefly skim the tutorial, and come back to it once you have
38+
# written a few JuMP models.
39+
40+
using JuMP
41+
import HiGHS
42+
43+
# ## General rules for debugging
44+
45+
#
46+
47+
# Before all else, read the [Debugging chapter](https://benlauwens.github.io/ThinkJulia.jl/latest/book.html#chap21)
48+
# in the book [ThinkJulia.jl](https://benlauwens.github.io/ThinkJulia.jl/latest/book.html).
49+
50+
#
51+
52+
# * Simplify the problem
53+
54+
# ## Debugging an infeasible model
55+
56+
# ## Debugging an unbounded model
57+
58+
# A model is unbounded if there is no limit on how good the objective value can
59+
# get. In general, an unbounded model means that you have an error in your
60+
# modeling, because all physical systems have limits. (You cannot make an
61+
# infinite amount of profit.)
62+
63+
# A simple example of an unbounded model is:
64+
65+
model = Model(HiGHS.Optimizer)
66+
set_silent(model)
67+
@variable(model, x >= 0)
68+
@objective(model, Max, 2x + 1)
69+
70+
# because we can increase `x` without limit, and the objective value `2x + 1`
71+
# gets better as `x` increases.
72+
73+
# JuMP doesn't have an `UNBOUNDED` termination status. Instead, unbounded models
74+
# will return `DUAL_INFEASIBLE`:
75+
76+
optimize!(model)
77+
termination_status(model)
78+
79+
# Common sources of unboundedness are:
80+
#
81+
# * Using `Max` instead of `Min`
82+
# * Omitting variable bounds, such as `0 <= x <= 1`
83+
# * Using `+` instead of `-` in a term of the objective function.
84+
85+
# Strategies to debug sources of unboundedness are:
86+
87+
# * Double check whether you intended `Min` or `Max` in the [`@objective`](@ref)
88+
# line.
89+
# * Print the objective function with `print(objective_function(model))` and
90+
# verify that the value and sign of each coefficient is as you expect.
91+
# * Add large bounds to all variables that are free or have one-sided bounds,
92+
# then re-solve the problem. Because all variables are now bounded, the
93+
# problem will have a finite optimal solution. Look at the value of each
94+
# variable in the optimal solution to see if it is at one of the new bounds.
95+
# If it is, you either need to specify a better bound for that variable, or
96+
# there might be a mistake in the objective function associated with that
97+
# variable (for example, a `+` instead of a `-`).
98+
99+
# If there are too many variables to add bounds to, or there are too many terms
100+
# to examine by hand, another strategy is to create a new variable with a large
101+
# upper bound (if maximizing, lower bound if minimizing) and a constraint that
102+
# the variable must be less-than or equal to the expression of the objective
103+
# function. For example:
104+
105+
model = Model(HiGHS.Optimizer)
106+
set_silent(model)
107+
@variable(model, x >= 0)
108+
## @objective(model, Max, 2x + 1)
109+
@variable(model, objective <= 10_000)
110+
@constraint(model, objective <= 2x + 1)
111+
@objective(model, Max, objective)
112+
113+
# This new model has a finite optimal solution, so we can solve it and then look
114+
# for variables with large positive or negative values in the optimal solution.

0 commit comments

Comments
 (0)