Knapsack¶
The 0/1 Knapsack problem can be described as follows. We are given a set of \(n\) items, labelled by the index \(i\) for \(i = 1,..,n\). The \(i^{th}\) item has value \(v_i\) and weight \(w_i\), and the goal is to choose a subset of the items such that the sum of the values of the chosen items is maximized, subject to the constraint that the sum of their weights does not exceed a specified capacity \(W\). The quantity \(W\) is typically called the weight capacity or the knapsack capacity. Clearly, for the problem to be non-trivial it must be the case that \(W\) is less than the sum of the weights of all items, otherwise we would choose the entire set.
The Cost Function¶
Mathematically, the problem may be stated as follows:
where a variable with value 1 indicates that the corresponding item is chosen to be in the knapsack.
In order to turn such a formulation into a QUBO one, we must first make the inequality constraint an equality. This is done by introducing extra variable (sometimes called "slack variables") \(y_1, \dots, y_k\) where \(k=\lfloor\log W\rfloor +1\), so that one can rewrite the inequality constraint as \(\sum_{i=1}^n w_i x_i + \sum_{i=0}^{k}2^iy_i = W\). This way, if the sum of the weights of the chosen items is less than or equal to \(W\) (which would mean the inequality constraint is satisfied), there is then some configuration of the slack variables that will allow the equality to be satisfied. In fact, the slack variables form the binary representation of the value needed to meet equality, which is why \(\sum_{i=0}^{k}2^iy_i\) appears. The new problem is thus
Now that we have an equality constraint, the corresponding QUBO formulation is retrieved by turning the constraint into a so-called quadratic penalty. That is, the cost function is
where \(\textbf{x} = \{0,1\}^n, \ \ \vec{y} = \{0, 1\}^k\).
This cost function can be converted in the form of an Ising formulation (so that variables take values in \(\{-1, 1\}\)) in order to be used with the QAOA algorithm (see what-is-a-qubo).
Knapsack in OpenQAOA¶
The knapsack problem can be defined by the value of each item, the weight of each item, the total capacity of the knapsack and the penalty associated with overloading the knapsack. We can create the Knapsack problem easily:
from openqaoa.problems import Knapsack
knapsack_prob = Knapsack.random_instance(n_items=4, seed=42)
knapsack_qubo = knapsack_prob.qubo
We can then access the underlying cost hamiltonian
You may also check all details of the problem instance in the form of a dictionary:
> knapsack_qubo.asdict()
{'constant': 116.0,
'metadata': {},
'n': 7,
'problem_instance': {'n_items': 4,
'penalty': 6,
'problem_type': 'knapsack',
'values': [1, 3, 2, 2],
'weight_capacity': 5,
'weights': [2, 3, 1, 3]},
'terms': [[0, 1],
[0, 2],
[1, 2],
[3, 4],
[3, 5],
[3, 6],
[4, 5],
[4, 6],
[5, 6],
[0, 3],
[0, 4],
[0, 5],
[0, 6],
[1, 3],
[1, 4],
[1, 5],
[1, 6],
[2, 3],
[2, 4],
[2, 5],
[2, 6],
[0],
[1],
[2],
[3],
[4],
[5],
[6]],
'weights': [6.0, 12.0, 24.0, 18.0, 6.0, 18.0, 9.0, 27.0, 9.0, 6.0, 9.0, 3.0, 9.0, 12.0, 18.0, 6.0, 18.0, 24.0, 36.0, 12.0, 36.0, -18.0, -36.0, -72.0, -35.5, -52.5, -17.0, -53.0]}