# How can I compare the previous value and the current value implemented during NestWhileList?

I am trying to write a part of my code. I am using NestWhileList. However, I couldn't find out the right syntax for testing. It should compare previous result and current result and continue if it is True.

I want to do this, for instance :

NestWhileList[# + RandomInteger[{-5, 5}] &, 10, previousresult <= currentresult];


and

If I have two test options for NestWhileList, for instance :

  NestWhileList[# + RandomInteger[{-5, 5}] &, 10, previousresult <= currentresult && previous result<0];


Is there a way to do it?

Second Question (This question is not absolutely related to first question.) In addition, if I can't do that, i will try to create a list without testing. If I create list, how can I compare successive two component of list in a functional way?

Any help is appreciated.

-
Look at the fourth argument – ssch Jan 15 '13 at 13:16
@ssch I used this argument, my goal is to learn how to use the previous value. And can you look at my edit? – cesm Jan 15 '13 at 13:28
The test is expected to be a function (something that takes arguments). A pure function seems suitable in this case. Here's an example from the NestWhileList doc: NestWhileList[(# + 2/# )/2 &, 1, Abs[#1 - #2] > 0.001 &, 2] – ssch Jan 15 '13 at 13:37
Regarding your edit, as you're starting from 10 and requiring previous result<0 the nesting will not even start. – b.gatessucks Jan 15 '13 at 13:37
@b.gatessucks I wrote this not thinking too much on it. My desire is to learn how to use the previous value. Thanks for attention. – cesm Jan 15 '13 at 13:49

I'm going to answer this because it provides an opportunity to show a simple method for examining the behavior of the test function. First the syntax from the documentation:

So let's try:

NestWhileList[# + 1 &, 0, (Print[#, " ", #2]; True) &, 2, 5]


0 1

1 2

2 3

3 4

{0, 1, 2, 3, 4, 5}


The function (Print[#, " ", #2]; True) & lets you easily see what is being passed to the test function at each step, and automatically aborts after five steps because of the last argument.

Here is another example. We end the loop when a certain ratio is exceeded:

NestWhileList[# + 1 &, 0, (Print["prev: ", #, "  current: ", #2]; 1 - #/#2 > 0.15) &, 2]


{0, 1, 2, 3, 4, 5, 6, 7}


Hopefully this method and example will help you work these things out for yourself more easily.

-
Maybe one could mention Reap and Sow as alternatives to Print - but I admit I use Print a lot this way too. (+1) – Jens Jan 15 '13 at 18:52
Thanks! That was what I want to learn about both NestWhileList and behaviour of the test functions. – cesm Jan 16 '13 at 9:33

I assume you just want to compare current and previous values for the purposes of the stopping condition. Then using NestWhileList with the additional argument as in the comment by ssch is the obvious way to go. This is just another option:

For the stopping criterion, there is one alternative that I've found to be a little faster by trial and error. Instead of NestWhileList, you can use FixedPointList with a custom setting for the option SameTest. The difference is that you then also have to specify a maximum number of iteration steps after which you'd like to terminate unconditionally. This helps prevent runaway loops. And given your specific example with random numbers, that may be a real concern.

Here is your example in my approach:

FixedPointList[# + RandomInteger[{-5, 5}] &, 10, 100,
SameTest -> (#2 <= #1 &)]

(* ==> {10, 13, 16, 18, 20, 21, 17} *)


The argument 100 limits the calculation to that many trials. The SameTest -> (#2 <= #1 &) is the crucial part, implementing the stopping criterion, where #1 stands for the current argument and #2 for the previous argument. Unlike NestWhileList, these are provided automatically. The function SameTest can be anything you want, Mathematica doesn't care if it actually implements any real "sameness" of successive arguments. That's why it can be used here.

I just remembered another reason why I try to use FixedPoint and FixedPointList when possible: it's in the list of functions that can be compiled.

Finally, another point that may not be what you want: If you need the two arguments inside the function that's being iterated, then you can always do that by making the iterated function into a list that returns its own argument and the computed new value as a tuple. Another approach would be to use FoldList, but that's useful mainly if you don't need to implement a specific stopping criterion.

-
Thank you for your beneficial information. I have looked for FixedPointList for my program but it doesn't work because of specifying max number of iterations. – cesm Jan 16 '13 at 9:38