Reputation: 408
When I run
weights <- 1:50
profits <- 1:50
library(adagio)
knapsack(w = weights, p = profits, cap = 30)
I get the error
Error in F[, k] <- G :
number of items to replace is not a multiple of replacement length
In addition: Warning message:
In pmax(G, H) : an argument will be fractionally recycled
but when I run smaller sized vectors, like
weights <- 1:20
profits <- 1:20
knapsack(w = weights, p = profits, cap = 30)
it runs fine. Does knapsack() just slow down (and prevent running) for larger sets? I'm looking to use lengths in the thousands eventually.
Upvotes: 2
Views: 305
Reputation: 265
I received the same error (which is how I got this SO post..) I think that the adagio knapsack function doesn't like profits or weights that are fractional values. I used rnorm() to generate profits and weights, to compare their results to another knapsack function that I personally wrote. Even with a capacity that was several times larger than all the weights put together, I was getting the 'recycling' error. However when I rounded off the rnorm() vectors before passing them as arguments to knapsack, no problems.
Upvotes: 1
Reputation: 44330
This is an issue with passing elements with weight exceeding the total capacity. To see the issue, let's look at the first few lines of the knapsack
function:
function (w, p, cap)
{
n <- length(w)
x <- logical(n)
F <- matrix(0, nrow = cap + 1, ncol = n)
G <- matrix(0, nrow = cap + 1, ncol = 1)
for (k in 1:n) {
F[, k] <- G
H <- c(numeric(w[k]), G[1:(cap + 1 - w[k]), 1] + p[k])
G <- pmax(G, H)
}
When iteratively filling the F
matrix one column at a time, the algorithm creates a vector H
with the following command (and then immediately computing pmax(G, H)
):
H <- c(numeric(w[k]), G[1:(cap + 1 - w[k]), 1] + p[k])
numeric(w[k])
has length w[k]
, and when w[k] <= cap
, G[1:(cap + 1 - w[k]), 1] + p[k]
has length cap + 1 - w[k]
, meaning the entire vector H
has length cap+1
, matching the size of G
. On the other hand, when w[k] == cap + 1
we will end up with an H
vector of size cap+2
, which doesn't match the size of G
and gives us trouble, and with w[k] > cap + 1
we will get an error for mixing positive and negative indices.
Getting back to your example function call, you have weights up to 50 but only a capacity of 30, yielding an error:
weights <- 1:50
profits <- 1:50
knapsack(w = weights, p = profits, cap = 30)
# Error in F[, k] <- G :
# number of items to replace is not a multiple of replacement length
# In addition: Warning message:
# In pmax(G, H) : an argument will be fractionally recycled
However when you limit to elements with weight not exceeding the capacity, you get no errors:
knapsack(w = weights[weights <= 30], p = profits[weights <= 30], cap = 30)
# $capacity
# [1] 30
#
# $profit
# [1] 30
#
# $indices
# [1] 1 2 3 4 5 7 8
It would be most ideal if the knapsack
function gracefully removed any object with weight exceeding the capacity (since no such elements could ever be used in a feasible solution) and gave you a solution for the code you posted, but as a workaround you could simply remove them yourself from the input to the knapsack
function.
Upvotes: 2