Fractional Knapsack Problem
Overview
The Knapsack problem is a class of optimization problems in which we have to find the maximal answer among all the various possibilities given in the question. There are three types of knapsack problems 0-1 Knapsack, Fractional Knapsack, and Unbounded Knapsack. In this article, we will be seeing the fractional knapsack Problem in detail.
Introduction to Fractional Knapsack Problem
Given two arrays named value and weight of size each, where value[i] represents the value and weight[i] represents the weight associated with the item. Also, we have been provided a knapsack with a maximum capacity of W.
The task is to pick some items (possibly all of them) such that the sum of values of all the items is maximized and the sum of weights of all the items is at most W.
As the name Fractional suggests, here we are allowed to take a fraction of an item. For example, if the weight of an item is units, then we can have the following choices :
- Do not take any fraction of the item.
- Take the item as a whole.
- Take any integer weight of the item For an item of weight Kg. we can either take Kg, Kg, ..., or Kg but we are not allowed to take Kg or Kg.
Note that if we are taking a fraction of an item, we get the value in the same fraction.
Example
Input :
Output :
Explanation :
Let's say we take the item as a whole, so we obtain a value of40and the capacity of the knapsack is now reduced to50. Then we pick the item as a whole, after which we obtain a value of120and the capacity of the knapsack is now reduced to30.
Now we take 30 Kg. of the item, which will add to our value due to which we obtained a value of 162 and we are left with no space in the knapsack hence we can conclude the result to be 162.
It can be proved that there is no other choice of picking item(s) such that the value of the chosen item(s) exceeds 162.
Techniques to Solve the Fractional Knapsack Problem
Brute Force Approach
Since for an item of weight , we have choices taking 0 Kg. of the item, taking 1 Kg. of the item, taking 2 Kg. of the item, ...., taking Kg. of the item. Therefore, with the brute force approach, we can check the value of all the possibilities from the set of items provided.
As discussed above, for the item we have choices, and hence the total number of possibilities is KaTeX parse error: $ within math mode. Therefore, the time complexity of the brute force approach is
Example :
Let's say we have the following items :
Item no. | Weight | Value |
---|---|---|
1 | 1 | 3 |
2 | 1 | 6 |
3 | 1 | 5 |
And a knapsack with a capacity of 3.
So, as per the brute force algorithm, we can have the following choices : In the below-given matrix, the value in the denotes the amount of weight of item we are taking in the choice.
Total Value | |||
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 0 | 1 | 5 |
0 | 1 | 0 | 6 |
0 | 1 | 1 | 11 |
1 | 0 | 0 | 3 |
1 | 0 | 1 | 8 |
1 | 1 | 0 | 9 |
1 | 1 | 1 | 14 |
The highest possible value we can obtain is 14 by picking the 1 Kg. of all the items.
Greedy Approach
We have seen that the brute force approach works every time but on a reasonable large input, it will take a very huge amount of time to calculate the answer.
So, we can opt for a greedy algorithm. We can have several potentially correct strategies, some of the obvious ones are :
- Picking the items with the largest values first.
- Picking the items with the lowest weights first.
- Picking the items based on some sort of ratio among their values and weights.
In the next section of this article, we will see which of the above approach is correct and the reason behind their correctness.
Example of Solving a Fractional Knapsack Problem Using Three Approaches
Let's say we have the following input :
Items :
Item No. | Weight | Value |
---|---|---|
1 | 10 | 40 |
2 | 30 | 20 |
3 | 20 | 80 |
4 | 50 | 70 |
5 | 20 | 50 |
Capacity (W) : 70
Approach - 1 : Picking Items with the Largest Value
Item No. | Weight | Value | Remaining Space |
---|---|---|---|
3 | 20 | 80 | 70 - 20 = 50 |
4 | 50 | 70 | 50 - 50 = 0 |
Using the approach we can obtain a value of
Approach - 2 : Picking Items with the Smallest Weight
Item No. | Weight | Value | Remaining Space |
---|---|---|---|
1 | 10 | 40 | 70 - 10 = 60 |
3 | 20 | 80 | 60 - 20 = 40 |
5 | 20 | 50 | 40 - 20 = 20 |
2 | 30 | 20 - 20 = 0 |
Using the approach we can obtain a value of
Approach - 3 : Picking Items Based on Ratio
As per this approach, we will find the value obtained per unit weight for all items. And we will take the items with the largest value per unit weight first. So we will have our input modified to :
Item No. | Weight | Value | |
---|---|---|---|
1 | 10 | 40 | |
2 | 30 | 20 | |
3 | 20 | 80 | |
4 | 50 | 70 | |
5 | 20 | 50 |
Now picking items as follows :
Item No. | Weight | Value | Remaining Space |
---|---|---|---|
1 | 10 | 40 | 70 - 10 = 60 |
3 | 20 | 80 | 60 - 20 = 40 |
5 | 20 | 50 | 40 - 20 = 20 |
4 | 50 | 40 - 20 = 0 |
Using the approach we can obtain a value of
We can see that by following the third approach we can obtain the maximum value. This is because in other approaches we were giving importance to only one parameter but in the third approach, we considered the ratio of both to obtain the maximal value.
Also, another possible way is to find the ratio of Weight Gained Per unit value (which is reciprocal of the current ratio), and then choose items in ascending order of the ratio's value.
Greedy Algorithm
As seen in the previous section, for each item we will calculate the ratio of value to its weight which denotes the value obtained per unit weight.
Now to get the maximal value, we will sort the items in the descending order of the ratio so that items with greater ratio values are picked before items with a comparatively smaller ratio.
While picking an item, we will check if it is possible to take it as a whole or not because we are constrained by the capacity of the knapsack. So, if it is not possible to pick the item as a whole, we will pick as much weight of the item as we can.
The algorithm is as follows :
- Sort the items in descending order using a custom comparator based on the value per unit weight ratio.
- Declare a variable of floating-point type, ans, and initialize it with 0.
- Iterate from To Item.length and do the following :
- If it is possible to take the item[i] as a whole do the following :
- Add value[i] to the ans, because we have picked this item as a whole.
- Subtract weight[i] from the Capacity, because picking this item will reduce the capacity.
- Otherwise do the following :
- Let's say you are left with capacity .
- Add to ans.
- Subtract from Capacity.
- Terminate the loop as the Knapsack is full.
- If it is possible to take the item[i] as a whole do the following :
- Return the result ans.
Pseudocode
Java Implementation
Output :
C++ Implementation
Output :
Python Implementation
Output :
C# Implementation
Output :
Complexity Analysis
-
Time Complexity :
Sorting the item set will require at least time, and Iterating over the sorted item set will require time. Hence the overall time complexity is -
Space Complexity :
Doesn't matter which sorting algorithm we use for sorting, it will require extra space because we need to combine value and weight arrays using a 2-D array/list to sort them. Hence the overall space complexity is .
Bonus Tip
We have seen the time complexity to be but in the best case, we can optimize it further to .
Let's see how :
If the capacity of our knapsack is greater than or equal to the sum of the weights of all the items, we do not need to sort items. Instead, we can select all the items available because we have hefty space to accommodate all of them.
So, in this case, we just need to find the sum of all the values which will require time.
Conclusion
- In the fractional knapsack problem, we are allowed to split the items in fractions, unlike the 0-1 Knapsack problem where it is prohibited to split the items.
- Checking for all the possible choices of picking items works well but requires a huge amount of time.
- The Greedy approach uses the value per unit weight ratio of items to select the best choices.