KnapSack dynamic programming in R with recursive function - r

I created this simple code in R to solve the Knapsack program with a recursive funtion
n <- c(0,1,2,3,4)
v <- c(10,40,30,50)
w <- c(5,4,6,3)
k <- 10
myfunction <- function(n,k){
if (n==0 | k==0){
output <- 0
} else if (w[i] > k) {
output <- myfunction[i-1,w]
} else {
output <- max(v[i]+ myfunction(i-1, k-w[i]),myfunction(i-1,k))
}
return(myfunction)
}
However, I don't get a value as an output, but the whole function. For example if I put in:
myfunction(4,10)
I don't get an value of 90, but the whole funtion typed out.
these are the values

There were several errors beyond the ones pointed out by #etienne. Here's an annotated debugging session. First we fix the returned object:
> myfunction <- function(n,k){
+ if (n==0 | k==0){
+ output <- 0
+ } else if (w[i] > k) {
+ output <- myfunction[i-1,w]
+ } else {
+ output <- max(v[i]+ myfunction(i-1, k-w[i]),myfunction(i-1,k))
+ }
+ return(output)
+ }
> myfunction(4,10)
Error in if (w[i] > k) { : argument is of length zero
Obviously neither w nor k are of length zero which suggests it must be i. (As also pointed out by etienne). Looking at your code it appears you actually intended i to be the index that decreased until the terminating condition was met. So replace n by i in the few instances where it appeared:
> myfunction <- function(i,k){
+ if (i==0 | k==0){
+ output <- 0
+ } else if (w[i] > k) {
+ output <- myfunction[i-1,w]
+ } else {
+ output <- max(v[i]+ myfunction(i-1, k-w[i]),myfunction(i-1,k))
+ }
+ return(output)
+ }
> myfunction(4,10)
Error in myfunction[i - 1, w] :
object of type 'closure' is not subsettable
So you also made the mistake of using square-brackets where parentheses (aka bracket in the non-US sections of the world) were needed:
> myfunction <- function(i,k){
+ if (i==0 | k==0){
+ output <- 0
+ } else if (w[i] > k) {
+ output <- myfunction(i-1,w)
+ } else {
+ output <- max(v[i]+ myfunction(i-1, k-w[i]),myfunction(i-1,k))
+ }
+ return(output)
+ }
> myfunction(4,10)
[1] 90
Success, well, almost. Most of the warnings are because you used | instead of || in one of the conditionals:
Warning messages:
1: In if (i == 0 | k == 0) { :
the condition has length > 1 and only the first element will be used
2: In if (w[i] > k) { :
the condition has length > 1 and only the first element will be used
3: In if (i == 0 | k == 0) { :
the condition has length > 1 and only the first element will be used
4: In if (i == 0 | k == 0) { :
the condition has length > 1 and only the first element will be used
5: In if (i == 0 | k == 0) { :
the condition has length > 1 and only the first element will be used
6: In if (i == 0 | k == 0) { :
the condition has length > 1 and only the first element will be used
So replace that instance with a logical ||. To deal with the other warning that didn't seem to sabotage your logic, realize that w[i] is length-0 when i == 0, so add a logical clause in the conditional that first tests for that possibility and use the correct "double-AND-sign" ( && ):
myfunction <- function(i,k){
if (i==0 || k==0){
output <- 0
} else if (length( w[i]) && w[i] > k) {
output <- myfunction(i-1,w)
} else {
output <- max(v[i]+ myfunction(i-1, k-w[i]), myfunction(i-1,k))
}
return(output)
}
Now you get:
> myfunction(4,10)
[1] 90

Related

Loop returns error: 'argument is of length zero'

i <- 2
j <- 0
for (i in 2:1000) {
if(return.prime(i)){j = j + 1}
i = i + 1
}
I want to check how many prime numbers there are in 1 to 1000 using my own function return.prime which returns TRUE when the number input is a prime and FALSE when the number input is not prime. The return.prime function is the function below and it is correct.
return.prime <- function(d){
if(d ==1 ){print(FALSE)}
if (d == 2){
print(TRUE)
}
if(d !=2 && d!=1){
if(any(d %% (2:(d-1)) == rep(0,d-2))==TRUE){
print(FALSE)}
else
print(TRUE)
}
}
The problem is when I run my program it says:
[1] TRUE
Error in if (return.prime(i)) { : argument is of length zero
I do not know what causes the length zero.
R doesn't work that way. You're just having the function print the word "TRUE" or "FALSE". Instead, you need to ?return TRUE or FALSE. Consider:
return.prime <- function(d){
if(d==1){ return(FALSE) }
if(d==2){ return(TRUE) }
if(d !=2 && d!=1){
if(any(d %% (2:(d-1)) == rep(0,d-2))==TRUE){
return(FALSE)
} else{
return(TRUE)
}
}
}
i <- 2
j <- 0
for (i in 2:1000) {
if(return.prime(i)){j = j + 1}
i = i + 1
}
j # [1] 168

Why can't I use in with an if condition

I have the following code:
x=rnorm(100,0,1)
x
a=0
for(i in x){
if(i in -1:1){
a<-a+1
}
}
I'm getting the following error:
Geeting error unexpected '}' in " }"
What am I doing wrong?
I changed the condition in the if statement. Is this what you want?
x=rnorm(100,0,1)
x
a = 0
for(i in x){
if(i > -1 & i < 1){
a <- a + 1
}
}

Use result of previous loop as input for next loop

I have the code below, which seems to accomplish what I'm trying to do but also throws the error output shown below the code. What I'm trying to do, is run through the loop the first time with x = 1, then for each time the loop runs after that I want x = y, the result of the previous loop. I always fumble with loops so any tips are greatly appreciated.
Code:
for(i in 1:5)
{
if(i=1)
{
x<-1
}
else
{
x<-y
}
y<-x*i
y
}
ERRORS:
for(i in 1:5)
+ {
+ if(i=1)
Error: unexpected '=' in:
"{
if(i="
> {
+ x<-1
+ }
> else
Error: unexpected 'else' in " else"
> {
+ x<-y
+ }
> y<-x*i
> y
[1] 25
> }
Error: unexpected '}' in "}"
Here is your code re-written with slightly clearer syntax
for (i in 1:5) {
if (i == 1) {
x <- 1
} else {
x <- y
}
y <- x * i
}
Or even better syntax.
for (i in 1:5) {
x <- ifelse(i == 1, 1, y)
y <- x * i
}

MATLAB to R Conversion: Append values to an existing empty array through for loop

I have the below code with me. This code was written originally in MATLAB. I have two questions here:
1) What would be the corresponding command in R for the below command in MATLAB:
duet(i).p = [];
2) In the below code I am getting all the correct 6 values for duet$n, but I am not getting correct values for duet$p. My question is how to append the values to an empty existing array duet$p[i] in R through the for loop iterations.
This line is not working in the below code:
duet$p[i] <- c(duet$p[i],j)
I might also have declared duet$p[i] <- array() incorrectly.
The values for duet.n and duet.p from MATLAB are:
duet.n
2 0 2 0 1 3
duet.p
[] [3,6] [] [1,3,5,6] [1,6] []
In R, I am getting duet$n values correctly, but I am not able to get the array kind of results for duet$p.
Any help to get the duet$p values would be appreciated.
x <- matrix(c(-1,2,4,1,7,4.2,3,0,1.2,-1.2,5.1,4,2,3.1,1.1,1,1,9,0,1,2,2,8,1,2,2,2,2,2,2),nrow=6,ncol=5,byrow=T)
fro=1;N=6;M=2;V=3;
F <- list(f=c())
duet = list()
for (i = 1 : N){
duet$n[i] = 0
duet$p[i] = array() ## Create an empty array
for (j in 1 : N){
dl = 0
de = 0
dm = 0
for (k = 1 : M){
if (x[i,V + k] < x[j,V + k]){
dl = dl + 1
} else if (x[i,V + k] == x[j,V + k]){
de = de + 1
} else{
dm = dm + 1
}
}
if (dl == 0 & de != M){
duet$n[i] = duet$n[i] + 1
} else if (dm == 0 & de != M){
duet$p[i] = c(duet$p[i],j)
}
}
if (duet$n[i] == 0){
x[i,6] = 1
F$f = c(F$f,i)
}
}
This appears to get the output you want:
x <- matrix(c(-1,2,4,1,7,4.2,3,0,1.2,-1.2,5.1,4,2,3.1,1.1,1,1,9,0,1,2,2,8,1,2,2,2,2,2,2),nrow=6,ncol=5,byrow=T)
fro=1;N=6;M=2;V=3;
F <- list(f=c())
duet = list(n=rep(0,N), p=lapply(1:N, function(x)c()))
for (i in 1 : N){
duet$n[i] = 0
#duet$p[[i]] = c() ## Create an empty array
#if(i==2) browser()
for (j in 1 : N){
k=1:M
dl <- sum(x[i,V + k] < x[j,V + k])
de <- sum(x[i,V + k] == x[j,V + k])
dm <- sum(x[i,V + k] > x[j,V + k])
if (dl == 0 & de != M){
duet$n[i] = duet$n[i] + 1
} else if (dm == 0 & de != M){
duet$p[[i]] = c(duet$p[[i]],j)
}
}
if (duet$n[i] == 0){
#x[i,6] = 1
F$f = c(F$f,i)
}
}
What have I done?
commented out the line x[i,6] =1, because there isn't an x[i,6], and I'm not sure what you meant it to be. You will need to sort this out.
Initialised duet$n as a vector
Initialised duet$p as a list of n empty vectors
removed the k loop as conditional counting in R can be done as the sum of elements where the condition is TRUE.
corrected the syntax of for loops: = became in
I think you're trying to do duet[i]$p instead of what you're doing. Also you need to initialize each cell as a list

Error in mutiple if statements

I am writing the following code in R but it gives me an error
S=function(x,a){
if(x<=a) {return (g)}
else
if (a < x <= b) {return(h)}
> Error: unexpected '<=' in:
> "
> else if (a < x <="
> else (return(i))
> }
How do I correct it?
So, I have rewritten your function to compile and eval, but I have no idea what it does for your problem.
S=function(x, a, b){
if (x <= a){
return(a)
}
else if ((a < x) && (x <= b)){ # break up the compound into two tests
return(a)
}
else{
return(a)
}
}
You need to pass b and I don't know what h,g were, but they weren't being assigned in your function declaration.
> S(1,2,3)
[1] 2

Resources