Current section

Files

Jump to
fixpoint lib examples knapsack.ex
Raw

lib/examples/knapsack.ex

defmodule CPSolver.Examples.Knapsack do
@moduledoc """
The 'knapsack' problem is mathematically formulated in
the following way. Given n items to choose from, each item i ∈ 0 ...n − 1 has a value v[i] and a
weight w[i]. The knapsack has a limited capacity K. Let x[i] be a variable that is 1 if you choose
to take item i and 0 if you leave item i behind. Then the knapsack problem is formalized as the
following optimization problem:
Maximize sum(x[i]*v[i]), i = 0 ... n - 1
subject to sum(x[i] * w[i]) <= K
Input data:
First line: "n K"
Next lines: "value weight"
"""
alias CPSolver.IntVariable, as: Variable
alias CPSolver.Constraint.Sum
alias CPSolver.Constraint.LessOrEqual
import CPSolver.Variable.View.Factory
def model(values, weights, capacity) do
items = Enum.map(1..length(values), fn i -> Variable.new(0..1, name: "item_#{i}") end)
total_weight = Variable.new(0..capacity, name: "total_weight")
total_value = Variable.new(0..Enum.sum(values), name: "total_value")
constraints = [
Sum.new(
total_weight,
Enum.map(
Enum.zip(items, weights),
fn {item, weight} -> mul(item, weight) end
)
),
Sum.new(
total_value,
Enum.map(
Enum.zip(items, values),
fn {item, value} -> mul(item, value) end
)
),
LessOrEqual.new(total_weight, capacity)
]
%{
# |> Enum.reverse(),
variables: items ++ [total_weight, total_value],
constraints: constraints
}
end
def model(input) do
input
|> File.read!()
|> String.trim()
|> String.split("\n")
|> then(fn lines ->
[header | item_data] = lines
capacity = String.split(header, " ") |> List.last() |> String.to_integer()
{values, weights} =
List.foldr(item_data, {[], []}, fn str, {vals_acc, weights_acc} ->
[v, w] = String.split(str, " ")
{
[String.to_integer(v) | vals_acc],
[String.to_integer(w) | weights_acc]
}
end)
model(values, weights, capacity)
end)
end
end