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*
精彩评论