开发者

Terminating an apply-based function early (similar to break?)

I am searching for a way to terminate an apply function early on some condition. Using a for loop, something like:

FDP_HCFA = function(FaultMatrix, TestCosts, GenerateNeighbors, RandomSeed) {    
  set.seed(RandomSeed)

  ## number of tests, mind the summary column
  nT = ncol(FaultMatrix) - 1
  StartingSequence = sample(1:nT)
  BestAPFD = APFD_C(StartingSequence, FaultMatrix, TestCosts)
  BestPrioritization = StartingSequence
  MakingProgress = TRUE
  NumberOfIterations = 0
  while(MakingProgress) {
    BestPrioritizationBefore = BestPrioritization
    AllCurrentNeighbors = GenerateNeighbors(BestPrioritization)

    for(Cur开发者_Go百科rentNeighbor in AllCurrentNeighbors) {
      CurrentAPFD = APFD_C(CurrentNeighbor, FaultMatrix, TestCosts)

      if(CurrentAPFD > BestAPFD) {
        BestAPFD = CurrentAPFD
        BestPrioritization = CurrentNeighbor            
        break
      }
    }

    if(length(union(list(BestPrioritizationBefore),
                    list(BestPrioritization))) == 1)
      MakingProgress = FALSE

    NumberOfIterations = NumberOfIterations + 1
  }
}

I would like to rewrite this function using some derivation of apply. In particular, terminating the evaluation of the first individual with increased fitness, thereby avoiding the cost of considering the rest of the population.


I reckon that you don't really grasp the apply family and its purpose. Contrary to the general idea, they're not the equivalent of any for-loop. One can say that most for-loops are the equivalent of an apply, but that's another matter.

Apply does exactly as it says: it applies a function on a number of similar arguments sequentially, and returns the result. Hence, by definition you cannot break out of an apply. You're not operating in the global environment any more, so in principle you cannot keep global counters, check after each execution some condition and adapt the loop. You can access the global environment and even change variables using assign or <<-, but this is pretty dangerous.

To understand the difference, don't read apply(1:3,afunc) as for(i in 1:3) afunc(i), but as

afunc(1)
afunc(2)
afunc(3)

in one (block) statement. That reflects better what you're doing exactly. An equivalent for break in an apply simply doesn't make sense, as it is more a block of code than a loop.


Aside from getting your sample code to work* I think this is a clear case where a loop is the right choice. Although R can apply a function to a whole vector of variables [EDIT: but you have to decide what they are before applying], in this case I'd use a while loop to avoid the cost of running unnecessary repetitions. Caveat: I know for loops have compared favorably with apply in timing tests, but I have not seen a similar test for while. Check out some of the options at http://cran.r-project.org/doc/manuals/R-lang.html#Control-structures.

while ( *statement1* ) *statement2*

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜