From: Francisco Gutierrez on
Dear group:
I have a function that gets five arguments, two of which are fixed, and three vary. Its output are three numbers. So it can be nested, for example over some initial values.
Say:
Nest[func[arg1,arg2,#[[1]],#[[2]],#[[3]]]&,{init1,init2,init3},k]

Simple enough, works well.
Now I want to nest the same function, while the second non fixed argument changes at each step. I thought the "natural" way of doing this was:
NestWhile[func[arg1,arg2,#[[1]],#[[2]],#[[3]]]&,{init1,init2,init3},UnsameQ[#[[2]]&,2],
but this evidently does not work.

So: in a NestWhile how do I create tests over parts of the outputs of a function?
Thanks!
Fg

From: Leonid Shifrin on
Hi Francisco,

When you use NestWhile and wish to access several past results, they should
correspond to different arguments of your test function.

Here is some specific function:

Clear[func];
func[x_, y_, z_, p_, q_] := IntegerPart[{z, p, q}^0.9]

Here is how we can use it to achieve what you want:

In[2]:= NestWhileList[
func[1, 2, #[[1]], #[[2]], #[[3]]] &, {1, 100, 1000},
UnsameQ[#1[[2]], #2[[2]]] &, 2]

Out[2]= {{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}, {1, 28,
153}, {1, 20, 92}, {1, 14, 58}, {1, 10, 38}, {1, 7, 26}, {1, 5,
18}, {1, 4, 13}, {1, 3, 10}, {1, 2, 7}, {1, 1, 5}, {1, 1, 4}}

I used NestWhileList to make it more transparent what's going on. Or, in
this case, it may be less confusing to use pure function with named
arguments for the test:

In[3]:= NestWhileList[
func[1, 2, #[[1]], #[[2]], #[[3]]] &, {1, 100, 1000},
Function[{this, prev}, UnsameQ[this[[2]], prev[[2]]]], 2]

Out[3]= {{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}, {1, 28,
153}, {1, 20, 92}, {1, 14, 58}, {1, 10, 38}, {1, 7, 26}, {1, 5,
18}, {1, 4, 13}, {1, 3, 10}, {1, 2, 7}, {1, 1, 5}, {1, 1, 4}}

Note that the first argument is the "oldest" result and the last argument is
the most recent one, and the total number of arguments to the test function
is regulated by the fourth parameter to NestWhile(List) - 2 in our case.
Note also that pure functions silently ignore excessive arguments passed to
them. These two facts imply that you may get obscure mistakes if you specify
the wrong (too large) number of most recent results *and* use a pure
function for testing.

Hope this helps.

Regards,
Leonid


On Wed, Jan 20, 2010 at 2:50 PM, Francisco Gutierrez <fgutiers2002(a)yahoo.com
> wrote:

> Dear group:
> I have a function that gets five arguments, two of which are fixed, and
> three vary. Its output are three numbers. So it can be nested, for example
> over some initial values.
> Say:
> Nest[func[arg1,arg2,#[[1]],#[[2]],#[[3]]]&,{init1,init2,init3},k]
>
> Simple enough, works well.
> Now I want to nest the same function, while the second non fixed argument
> changes at each step. I thought the "natural" way of doing this was:
>
> NestWhile[func[arg1,arg2,#[[1]],#[[2]],#[[3]]]&,{init1,init2,init3},UnsameQ[#[[2]]&,2],
> but this evidently does not work.
>
> So: in a NestWhile how do I create tests over parts of the outputs of a
> function?
> Thanks!
> Fg
>
>
From: Leonid Shifrin on
Francisco,

This is a follow-up to my previous post. To be logically correct, the
example I gave with a test function with named arguments had to be with the
order of arguments interchanged:

Function[{prev, this}, UnsameQ[this[[2]], prev[[2]]]]

instead of

Function[{this, prev}, UnsameQ[this[[2]], prev[[2]]]]

Sorry for the confusion.

Regards,
Leonid



On Wed, Jan 20, 2010 at 2:50 PM, Francisco Gutierrez <fgutiers2002(a)yahoo.com
> wrote:

> Dear group:
> I have a function that gets five arguments, two of which are fixed, and
> three vary. Its output are three numbers. So it can be nested, for example
> over some initial values.
> Say:
> Nest[func[arg1,arg2,#[[1]],#[[2]],#[[3]]]&,{init1,init2,init3},k]
>
> Simple enough, works well.
> Now I want to nest the same function, while the second non fixed argument
> changes at each step. I thought the "natural" way of doing this was:
>
> NestWhile[func[arg1,arg2,#[[1]],#[[2]],#[[3]]]&,{init1,init2,init3},UnsameQ[#[[2]]&,2],
> but this evidently does not work.
>
> So: in a NestWhile how do I create tests over parts of the outputs of a
> function?
> Thanks!
> Fg
>
>


From: DrMajorBob on
How about

Clear[func,func2, test]
func[x_, y_, z_, p_, q_] := IntegerPart[{z, p, q}^0.9]
func2[x_, y_][{z_, p_, q_}] := func[x, y, z, p, q]
test[{_, a_, _}, {_, b_, _}] := UnsameQ[a, b]
NestWhileList[func2[1, 2], {1, 100, 1000}, test, 2]

{{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}, {1, 28, 153}, {1, 20,
92}, {1, 14, 58}, {1, 10, 38}, {1, 7, 26}, {1, 5, 18}, {1, 4,
13}, {1, 3, 10}, {1, 2, 7}, {1, 1, 5}, {1, 1, 4}}

or

Clear[func3, test]
func3[{z_, p_, q_}] := IntegerPart[{z, p, q}^0.9]
test[{_, a_, _}, {_, b_, _}] := UnsameQ[a, b]
NestWhileList[func3, {1, 100, 1000}, test, 2]

{{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}, {1, 28, 153}, {1, 20,
92}, {1, 14, 58}, {1, 10, 38}, {1, 7, 26}, {1, 5, 18}, {1, 4,
13}, {1, 3, 10}, {1, 2, 7}, {1, 1, 5}, {1, 1, 4}}

Bobby

On Thu, 21 Jan 2010 03:50:03 -0600, Leonid Shifrin <lshifr(a)gmail.com>
wrote:

> Hi Francisco,
>
> When you use NestWhile and wish to access several past results, they
> should
> correspond to different arguments of your test function.
>
> Here is some specific function:
>
> Clear[func];
> func[x_, y_, z_, p_, q_] := IntegerPart[{z, p, q}^0.9]
>
> Here is how we can use it to achieve what you want:
>
> In[2]:= NestWhileList[
> func[1, 2, #[[1]], #[[2]], #[[3]]] &, {1, 100, 1000},
> UnsameQ[#1[[2]], #2[[2]]] &, 2]
>
> Out[2]= {{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}, {1, 28,
> 153}, {1, 20, 92}, {1, 14, 58}, {1, 10, 38}, {1, 7, 26}, {1, 5,
> 18}, {1, 4, 13}, {1, 3, 10}, {1, 2, 7}, {1, 1, 5}, {1, 1, 4}}
>
> I used NestWhileList to make it more transparent what's going on. Or, in
> this case, it may be less confusing to use pure function with named
> arguments for the test:
>
> In[3]:= NestWhileList[
> func[1, 2, #[[1]], #[[2]], #[[3]]] &, {1, 100, 1000},
> Function[{this, prev}, UnsameQ[this[[2]], prev[[2]]]], 2]
>
> Out[3]= {{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}, {1, 28,
> 153}, {1, 20, 92}, {1, 14, 58}, {1, 10, 38}, {1, 7, 26}, {1, 5,
> 18}, {1, 4, 13}, {1, 3, 10}, {1, 2, 7}, {1, 1, 5}, {1, 1, 4}}
>
> Note that the first argument is the "oldest" result and the last
> argument is
> the most recent one, and the total number of arguments to the test
> function
> is regulated by the fourth parameter to NestWhile(List) - 2 in our case.
> Note also that pure functions silently ignore excessive arguments passed
> to
> them. These two facts imply that you may get obscure mistakes if you
> specify
> the wrong (too large) number of most recent results *and* use a pure
> function for testing.
>
> Hope this helps.
>
> Regards,
> Leonid
>
>
> On Wed, Jan 20, 2010 at 2:50 PM, Francisco Gutierrez
> <fgutiers2002(a)yahoo.com
>> wrote:
>
>> Dear group:
>> I have a function that gets five arguments, two of which are fixed, and
>> three vary. Its output are three numbers. So it can be nested, for
>> example
>> over some initial values.
>> Say:
>> Nest[func[arg1,arg2,#[[1]],#[[2]],#[[3]]]&,{init1,init2,init3},k]
>>
>> Simple enough, works well.
>> Now I want to nest the same function, while the second non fixed
>> argument
>> changes at each step. I thought the "natural" way of doing this was:
>>
>> NestWhile[func[arg1,arg2,#[[1]],#[[2]],#[[3]]]&,{init1,init2,init3},UnsameQ[#[[2]]&,2],
>> but this evidently does not work.
>>
>> So: in a NestWhile how do I create tests over parts of the outputs of a
>> function?
>> Thanks!
>> Fg
>>
>>


--
DrMajorBob(a)yahoo.com

From: Leonid Shifrin on
Hi Bobby,

Well, these are certainly the possibilities, I just wanted to stay as close
to the original code of Francisco as possible. Removing this restriction,
conceptually your first example is better than my version since it clearly
separates the fixed and varying arguments. FWIW, your second version is not
up to Fransisco's specs, since he asked that his function explicitly takes 5
args and keeps the first two fixed, while in your second example the
function takes only three.

Defiining the test function through patterns, besides being easier to read,
seems to me a step in the right direction in avoiding the kind of errors I
mentioned (if that was the goal), but in the form you have it it does seem
to properly do so, since every outcome of the test function which is not
explicitly True is considered to be False by NestWhile(List), the behavior
which more likely than not is not what is desired:

In[1]:=
Clear[func, func2, test];
func[x_, y_, z_, p_, q_] := IntegerPart[{z, p, q}^0.9]
func2[x_, y_][{z_, p_, q_}] := func[x, y, z, p, q]
test[{_, a_, _}, {_, b_, _}] := UnsameQ[a, b]
NestWhileList[func2[1, 2], {1, 100, 1000}, test, 3]

Out[1] = {{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}}

If this (bullet-proofing) is at all an issue, I'd probably do it this way:

In[2]:=
ClearAll[func, func2, test]
test::argnum =
"test was called with `1` arguments. Two arguments were expected";
func[x_, y_, z_, p_, q_] := IntegerPart[{z, p, q}^0.9]
func2[x_, y_][{z_, p_, q_}] := func[x, y, z, p, q]
test[{_, a_, _}, {_, b_, _}] := UnsameQ[a, b];
test[x___] := (Message[test::argnum, Length[{x}]]; Throw[$Failed]);

In[3]:=
Catch(a)NestWhileList[func2[1, 2], {1, 100, 1000}, test, 3]

During evaluation of In[3]:= test::argnum: test was called with 3
arguments. Two arguments were expected

Out[3]= $Failed

This does not seem to make much sense here, but may make sense if different
test functions requiring different number of most recent results are
expected to be used, like here:

Clear[getFixedPoint]
getFixedPoint[start : {_, _, _}, testF_, testParNum_] :=
Catch(a)NestWhileList[func2[1, 2], start, testF, testParNum];

This will then guard against the wrong combination of testF and testParNum
being passed to getFixedPoint.

Regards,
Leonid


On Thu, Jan 21, 2010 at 9:31 PM, DrMajorBob <btreat1(a)austin.rr.com> wrote:

> How about
>
> Clear[func,func2, test]
>
> func[x_, y_, z_, p_, q_] := IntegerPart[{z, p, q}^0.9]
> func2[x_, y_][{z_, p_, q_}] := func[x, y, z, p, q]
> test[{_, a_, _}, {_, b_, _}] := UnsameQ[a, b]
> NestWhileList[func2[1, 2], {1, 100, 1000}, test, 2]
>
>
> {{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}, {1, 28, 153}, {1, 20,
> 92}, {1, 14, 58}, {1, 10, 38}, {1, 7, 26}, {1, 5, 18}, {1, 4,
> 13}, {1, 3, 10}, {1, 2, 7}, {1, 1, 5}, {1, 1, 4}}
>
> or
>
> Clear[func3, test]
> func3[{z_, p_, q_}] := IntegerPart[{z, p, q}^0.9]
> test[{_, a_, _}, {_, b_, _}] := UnsameQ[a, b]
> NestWhileList[func3, {1, 100, 1000}, test, 2]
>
>
> {{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}, {1, 28, 153}, {1, 20,
> 92}, {1, 14, 58}, {1, 10, 38}, {1, 7, 26}, {1, 5, 18}, {1, 4,
> 13}, {1, 3, 10}, {1, 2, 7}, {1, 1, 5}, {1, 1, 4}}
>
> Bobby
>
>
> On Thu, 21 Jan 2010 03:50:03 -0600, Leonid Shifrin <lshifr(a)gmail.com>
> wrote:
>
> Hi Francisco,
>>
>> When you use NestWhile and wish to access several past results, they
>> should
>> correspond to different arguments of your test function.
>>
>> Here is some specific function:
>>
>> Clear[func];
>> func[x_, y_, z_, p_, q_] := IntegerPart[{z, p, q}^0.9]
>>
>> Here is how we can use it to achieve what you want:
>>
>> In[2]:= NestWhileList[
>> func[1, 2, #[[1]], #[[2]], #[[3]]] &, {1, 100, 1000},
>> UnsameQ[#1[[2]], #2[[2]]] &, 2]
>>
>> Out[2]= {{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}, {1, 28,
>> 153}, {1, 20, 92}, {1, 14, 58}, {1, 10, 38}, {1, 7, 26}, {1, 5,
>> 18}, {1, 4, 13}, {1, 3, 10}, {1, 2, 7}, {1, 1, 5}, {1, 1, 4}}
>>
>> I used NestWhileList to make it more transparent what's going on. Or, in
>> this case, it may be less confusing to use pure function with named
>> arguments for the test:
>>
>> In[3]:= NestWhileList[
>> func[1, 2, #[[1]], #[[2]], #[[3]]] &, {1, 100, 1000},
>> Function[{this, prev}, UnsameQ[this[[2]], prev[[2]]]], 2]
>>
>> Out[3]= {{1, 100, 1000}, {1, 63, 501}, {1, 41, 269}, {1, 28,
>> 153}, {1, 20, 92}, {1, 14, 58}, {1, 10, 38}, {1, 7, 26}, {1, 5,
>> 18}, {1, 4, 13}, {1, 3, 10}, {1, 2, 7}, {1, 1, 5}, {1, 1, 4}}
>>
>> Note that the first argument is the "oldest" result and the last argument
>> is
>> the most recent one, and the total number of arguments to the test
>> function
>> is regulated by the fourth parameter to NestWhile(List) - 2 in our case.
>> Note also that pure functions silently ignore excessive arguments passed
>> to
>> them. These two facts imply that you may get obscure mistakes if you
>> specify
>> the wrong (too large) number of most recent results *and* use a pure
>> function for testing.
>>
>> Hope this helps.
>>
>> Regards,
>> Leonid
>>
>>
>> On Wed, Jan 20, 2010 at 2:50 PM, Francisco Gutierrez <
>> fgutiers2002(a)yahoo.com
>>
>>> wrote:
>>>
>>
>> Dear group:
>>> I have a function that gets five arguments, two of which are fixed, and
>>> three vary. Its output are three numbers. So it can be nested, for
>>> example
>>> over some initial values.
>>> Say:
>>> Nest[func[arg1,arg2,#[[1]],#[[2]],#[[3]]]&,{init1,init2,init3},k]
>>>
>>> Simple enough, works well.
>>> Now I want to nest the same function, while the second non fixed argument
>>> changes at each step. I thought the "natural" way of doing this was:
>>>
>>>
>>> NestWhile[func[arg1,arg2,#[[1]],#[[2]],#[[3]]]&,{init1,init2,init3},UnsameQ[#[[2]]&,2],
>>> but this evidently does not work.
>>>
>>> So: in a NestWhile how do I create tests over parts of the outputs of a
>>> function?
>>> Thanks!
>>> Fg
>>>
>>>
>>>
>
> --
> DrMajorBob(a)yahoo.com
>