Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to knapsack tutorial #3216

Merged
merged 4 commits into from
Feb 13, 2023
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 110 additions & 17 deletions docs/src/tutorials/linear/knapsack.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,134 @@
# v.2.0. If a copy of the MPL was not distributed with this file, You can #src
# obtain one at https://mozilla.org/MPL/2.0/. #src

# # The knapsack problem
# # The knapsack problem example

# Formulate and solve a simple knapsack problem:
#
# max sum(p_j x_j)
# st sum(w_j x_j) <= C
# x binary
# The purpose of this example is demonstrate how to formulate and solve a
# simple optimization problem.
# We use the knapsack problem for this purpose.

# ## Required packages

# This tutorial requires the following packages:

using JuMP
import HiGHS
import Test

function example_knapsack()
profit = [5, 3, 2, 7, 4]
weight = [2, 8, 4, 2, 5]
capacity = 10
# ## Formulation

# The simple [knapsack problem](https://en.wikipedia.org/wiki/Knapsack_problem)
# is a well-known type of optimization problem: given a set of items and
# a container with a fixed capacity, choose a subset of items having the greatest combined
# value that will fit within the container without exceeding the capacity.
# The name of the problem suggests its analogy to packing for a trip,
# where the baggage weight limit is the capacity and the goal is to pack the
# most profitable combination of belongings.

# We can formulate the problem as an integer linear program

# ```math
# \begin{aligned}
# \max \; & \sum_{i=1}^n c_i x_i \\
# s.t. \; & \sum_{i=1}^n w_i x_i \le C, \\
# & x_i \in \{0,1\},\quad \forall i=1,\ldots,n
# \end{aligned}
# ```

# or more compactly as

# ```math
# \begin{aligned}
# \max \; & c^\top x \\
# s.t. \; & w^\top x \le C \\
# & x \text{ binary },
# \end{aligned}
# ```

# where there is a choice between ``n`` items, with item ``i`` having weight ``w_i``,
# profit ``c_i`` and a decision variable ``x_i`` equal to 1 if the item is chosen
# and 0 if not.

# ## Data

# The data for the problem is two vectors (one for the profits
# and one for the weights) along with a capacity.
# For our example, we use a capacity of 10 units
capacity = 10;
# and vector data
profit = [5, 3, 2, 7, 4];
weight = [2, 8, 4, 2, 5];

# ## JuMP formulation

# Let's begin constructing the JuMP model for our knapsack problem.
# First, we'll create a `Model` object for holding model elements as
# we construct each part. We'll also set the solver that will
# ultimately be called to solve the model, once it's constructed.
model = Model(HiGHS.Optimizer)

# Next we need the decision variables for which items are chosen.
@variable(model, x[1:5], Bin)

# We now want to constrain those variables so that their combined
# weight is less than or equal to the given capacity.
@constraint(model, sum(weight[i] * x[i] for i in 1:5) <= capacity)

# Finally, we set an objective: maximise the combined profit of the
# selected items.
@objective(model, Max, sum(profit[i] * x[i] for i in 1:5))

# Let's print a human-readable description of the model and
# check that the model looks as expected:
print(model)

# We can now solve the optimization problem and inspect the results.
optimize!(model)
solution_summary(model)
odow marked this conversation as resolved.
Show resolved Hide resolved

# After working interactively, it is good practice to implement
# your model in a function.
# A function can be used to ensure that the model is given
# well-defined input data by validation checks, and that the
# solution process went as expected.

function solve_knapsack_problem(;
profit,
weight::Vector{T},
capacity::T,
) where {T<:Real}
N = length(weight)

## The profit and weight vectors must be of equal length.
@assert length(profit) == N

model = Model(HiGHS.Optimizer)
set_silent(model)
@variable(model, x[1:5], Bin)
## Objective: maximize profit

## Declare the decision variables as binary (0 or 1).
@variable(model, x[1:N], Bin)

## Objective: maximize profit.
@objective(model, Max, profit' * x)
## Constraint: can carry all

## Constraint: can carry all items.
@constraint(model, weight' * x <= capacity)

## Solve problem using MIP solver
optimize!(model)
println("Objective is: ", objective_value(model))
println("Solution is:")
for i in 1:5
print("x[$i] = ", value(x[i]))
println(", p[$i]/w[$i] = ", profit[i] / weight[i])
for i in 1:N
print("x[$i] = ", Int(value(x[i])))
println(", c[$i]/w[$i] = ", profit[i] / weight[i])
end
Test.@test termination_status(model) == OPTIMAL
Test.@test primal_status(model) == FEASIBLE_POINT
Test.@test objective_value(model) == 16.0
return
end

example_knapsack()
solve_knapsack_problem(; profit = profit, weight = weight, capacity = capacity)

# We observe that the chosen items (1, 4 and 5) have the best
# profit to weight ratio for in this particular example.