Рекурсивная функция: сохранять вывод каждого вызова в список

Я хотел бы сохранить вывод каждого вызова функции следующей рекурсивной функции в список. Более того, мне нужно знать, какая (j,l)-пара соответствует какому элементу результирующего списка.

Я создал урезанную версию, чтобы воспроизвести проблему. Пожалуйста, дайте мне знать, если я должен предоставить дополнительную информацию, чтобы помочь решить проблему. Любая помощь высоко ценится. Спасибо.

#the recursive function
phi <- function(phik,j,l,k,d) {
  if(j==0) {
    diag(d)
  }
  else{
    if(j==1) {
      if(l>k) {
        0 * diag(d)
      }
      else{
        phik[[l]]      
      }      
    }
    else {
      if(l>k) {
        0 + phi(phik,j-1,l,k,d) %*% phik[[1]]
      }
      else {
        phi(phik,j-1,l+1,k,d) + phi(phik,j-1,l,k,d) %*% phik[[1]]
      }      
    }
  }
}

#related stuff
set.seed(123456)
phik <- vector(mode="list", length=3)
phik[[1]] <- matrix(rnorm(n=16,mean=0,s=1),nrow=4)
phik[[2]] <- matrix(rnorm(n=16,mean=0,s=1),nrow=4)
phik[[3]] <- matrix(rnorm(n=16,mean=0,s=1),nrow=4)
d <- nrow(phik[[1]])
k <- length(phik)

#function call
phiout <- phi(phik,j=10,l=1,k=k,d=d)

person Andy    schedule 04.02.2014    source источник
comment
вы не производите никакой продукции; вы возвращаете значения.   -  person sds    schedule 05.02.2014


Ответы (1)


Итак, с рекурсивными функциями немного сложно, потому что, если вам нужны результаты промежуточных шагов, вы должны склеить их вместе в список. Конечно, это означает, что когда вы используете результаты рекурсии в функции, вам нужно извлечь нужное значение. Это звучит немного запутанно, но в вашем случае я просто имею в виду, что вы должны возвращать небольшой список phi, j и l на каждом шаге, но выводить только phi при умножении. Вот небольшой пример:

#the recursive function
phi <- function(phik,j,l,k,d) {
  if(j==0) 
    list(list(phi=diag(d),j=j,l=l))
  else{
    if(j==1) {
      if(l>k) 
        list(list(phi=0 * diag(d),j=j,l=l))
      else 
        list(list(phi=phik[[l]],j=j,l=l))
    }
    else {
      if(l>k) {
        first<-phi(phik,j-1,l,k,d)
        second<-list(list(phi=0 + first[[1]]$phi %*% phik[[1]], j=j,l=l))
        c(second,first)
      }
      else {
        first<-phi(phik,j-1,l+1,k,d) 
        second<-phi(phik,j-1,l,k,d) 
        third<-list(list(phi=first[[1]]$phi+(second[[1]]$phi %*% phik[[1]]), j=j, l=l))
        c(third,first,second)
      }
    }
  }
}

Вам может быть интересно, почему я вложил результаты в случаях с первого по третий (когда j равно 0 или 1). Если вы посмотрите на другие случаи, это может стать ясным. Когда l>kj не равно 0 или 1), то phi выполняется два вызова. В этом случае будет возвращено list с двумя наборами phi, i и j, поэтому это обязательно list из lists. Когда я хочу извлечь phi из возвращаемого значения, трудно сказать, будет ли это просто list или list из lists, поэтому я просто стандартизировал их все для одного и того же.

Я думаю, что утверждения return уродливы, но другие с этим не согласны. Вы можете добавить их, если хотите, но они совершенно не нужны (в данном случае).

Некоторый пример вывода:

set.seed(123456)
phik <- vector(mode="list", length=3)
phik[[1]] <- matrix(rnorm(n=16,mean=0,s=1),nrow=4)
phik[[2]] <- matrix(rnorm(n=16,mean=0,s=1),nrow=4)
phik[[3]] <- matrix(rnorm(n=16,mean=0,s=1),nrow=4)
d <- nrow(phik[[1]])
k <- length(phik)

phi(phik,j=2,l=3,k,d)
# [[1]]
# [[1]]$phi
#            [,1]      [,2]       [,3]       [,4]
# [1,] -0.9087417 -2.064341 -0.9962198  0.7713081
# [2,] -2.9595280 -5.330120 -4.0488408  2.3357631
# [3,] -1.3754167 -3.866457 -0.8592336  1.4135614
# [4,] -0.1021518 -4.332802  0.4883886 -2.2130314
# 
# [[1]]$j
# [1] 2
# 
# [[1]]$l
# [1] 3
# 
# 
# [[2]]
# [[2]]$phi
#      [,1] [,2] [,3] [,4]
# [1,]    0    0    0    0
# [2,]    0    0    0    0
# [3,]    0    0    0    0
# [4,]    0    0    0    0
# 
# [[2]]$j
# [1] 1
# 
# [[2]]$l
# [1] 4
# 
# 
# [[3]]
# [[3]]$phi
#            [,1]      [,2]       [,3]       [,4]
# [1,] -1.0461983  1.560074 -1.0713045  0.1582893
# [2,] -2.7488684  1.015088  0.9678209 -0.5019485
# [3,] -1.1298596  1.043994  0.1710325 -0.9659226
# [4,] -0.8616848 -1.115905 -0.8962503 -0.1137341
# 
# [[3]]$j
# [1] 1
# 
# [[3]]$l
# [1] 3
person nograpes    schedule 04.02.2014