MathGroup Archive 2002

[Date Index] [Thread Index] [Author Index]

Search the Archive

RE: Re: Setting up dummy variables

  • To: mathgroup at smc.vnet.net
  • Subject: [mg35951] RE: [mg35930] Re: [mg35813] Setting up dummy variables
  • From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
  • Date: Fri, 9 Aug 2002 05:17:59 -0400 (EDT)
  • Sender: owner-wri-mathgroup at wolfram.com

>-----Original Message-----
>From: Omega Consulting [mailto:omega_consulting at yahoo.com]
To: mathgroup at smc.vnet.net
>Sent: Thursday, August 08, 2002 12:06 PM
>Subject: [mg35951] [mg35930] Re: [mg35813] Setting up dummy variables
>
>
>At 01:41 AM 8/2/2002, Christopher Maierle wrote:
>>Hi all,
>>
>>How do I set up a function that behaves like the Mathematica 
>function Sum 
>>vis-a-vis
>>its treatment of dummy variables?  For example I can define 
>i=6 and then
>>enter
>>
>>Sum[f[i],{i,1,n}]
>>
>>and mathematica will not make the substitution i->6 even 
>though the output
>>generally still involves the dummy variable i.  I figure this 
>has something
>>to do with Modules, Blocks, and Holds but I'm not sure how to 
>put it all
>>together.  Any help would be greatly appreciated.
>>
>>-chris
>
>So what you want is this behavior:
>
>In[1]:=
>i=1;
>
>In[2]:=
>Sum[f[i],{i,0,5}]
>Out[2]=
>f[0]+f[1]+f[2]+f[3]+f[4]+f[5]
>
>There are two things you need to do:
>-Control the order of evaluation
>-Temporarily substitute with a dummy variable
>
>This will prevent the arguments from evaluating before we can use them.
>
>In[3]:=
>SetAttributes[MySum,HoldAll]
>
>There are two holds we need to maintain. First, we must hold the first 
>argument to prevent it from turning into f[1]. We do this by 
>wrapping the 
>function in Hold. Second, we must replace the iteration 
>variable, but we 
>need to replace the unevaluated form. We do this with 
>HoldPattern. Then 
>after the substitution we let evaluation occur by using 
>ReleaseHold. Now 
>you have a version of the function that you can iterate using 
>the dummy 
>variable.
>
>In[4]:=
>MySum[f_,{x_,xmin_,xmax_}]:=
>   Module[{newf,tmp},
>     newf=ReleaseHold[Hold[f]/.HoldPattern[x]:>tmp];
>      Apply[Plus,Table[newf,{tmp,xmin,xmax}]]
>     ]
>
>In[5]:=
>MySum[f[i], {i, 0, 5}]
>Out[5]=
>f[0] + f[1] + f[2] + f[3] + f[4] + f[5]
>
>--------------------------------------------------------------
>Omega Consulting
>"The final answer to your Mathematica needs"
>
>Spend less time searching and more time finding.
>http://www.wz.com/internet/Mathematica.html
>
>

These complications are not necessary (see also my first reply to this
posting: [mg35903] RE: [mg35882] dummy indices), if you use Table for
implementing the iterations:

In[10]:= Attributes[mysum3] = {HoldAll}; 

In[11]:= mysum3[expr_, iters : ({_Symbol, _, _} ..)] := 
  Plus @@ Flatten[Table[expr, iters], Length[{iters}] - 1]

In[12]:= mysum3[Sin[x^m + y^n], {m, 1, 3}, {n, 1, m}]
Out[12]=
Sin[x + y] + Sin[x^2 + y] + Sin[x^3 + y] + 
  Sin[x^2 + y^2] + Sin[x^3 + y^2] + Sin[x^3 + y^3]

or taking your example:

In[16]:= i = 99;

In[17]:= mysum3[f[i], {i, 0, 5}]
Out[17]=
f[0] + f[1] + f[2] + f[3] + f[4] + f[5]


Regard, that you may replace Plus by any function you like (Times e.g.), you
even may pass it as an argument to "mysum" (then better called "iterApply"
or something).

Things are more complicated however if you want to mimik the machinery of
Sum itself (or Table for that matter). Here is something I came up with:

In[18]:=
mysum3[expr_, iters : ({_Symbol, _, _} ..)] := 
  Module[{s = 0}, 
    Function[Null, 
        Block[{##}, 
            Fold[Function[{i, i0, i1}, 
                    Unevaluated[For[i = i0, i <= i1, ++i, #1]]] @@ #2 &, 
              Unevaluated[Unevaluated[s += expr]], 
              Reverse[{iters}]]][[1]], 
        {HoldAll}] @@ First[Thread[Hold[iters]]]; s]

In[19]:= mysum3[Sin[x^m + y^n], {m, 1, 3}, {n, 1, m}]
Out[19]= 
Sin[x + y] + Sin[x^2 + y] + Sin[x^3 + y] + 
  Sin[x^2 + y^2] + Sin[x^3 + y^2] + Sin[x^3 + y^3]


Some explanations are needed:

(1) the arguments of mysum3 are held, but might evaluate at the rhs after
substitution. This must be prevented with Block. That may be done easily if
they can be referred by name (as was done in my first reply). 

[mg35903]> In[6]:= Attributes[mysum2] = {HoldAll}; 
[mg35903]> In[7]:=
[mg35903]> mysum2[expr_, {i_Symbol, imin_, imax_}, {j_Symbol, jmin_, jmax_}]
:= 
[mg35903]>   Module[{s=0},
[mg35903]>   Block[{i = imin}, 
[mg35903]>    While[i <= imax, 
[mg35903]>      Block[{j = jmin}, 
[mg35903]>        While[j <= jmax, s += expr; ++j]]; ++i]]; s]
[mg35903]> 
[mg35903]> In[8]:= mysum2[Sin[x^m + y^n], {m, 1, 3}, {n, 1, m}]
[mg35903]> Out[8]=
[mg35903]> Sin[x + y] + Sin[x^2 + y] + Sin[x^3 + y] + 
[mg35903]>   Sin[x^2 + y^2] + Sin[x^3 + y^2] + Sin[x^3 + y^3]

Here things are more difficult, as we can't refer the parametric Symbols by
i, j (which become m, n at call time). First we have to extract the held
Symbols:

In[30]:= m = -5; n = m^2;
In[31]:=
mysum3[expr_, iters : ({_Symbol, _, _} ..)] := First[Thread[Hold[iters]]]

In[32]:= mysum3[{m,n}, {m, 1, 3}, {n, 1, m}]
Out[32]= Hold[m, n]

The more difficult part is to transfer them into Block unevaluated. (Try if
you like!) The idea I got (and am proud of) is:

In[33]:= 
mysum3[expr_, iters : ({_Symbol, _, _} ..)] := 
  Function[Null, Block[{##}, Print[expr]], {HoldAll}] @@ 
    First[Thread[Hold[iters]]]
In[34]:=
mysum3[{m,n}, {m, 1, 3}, {n, 1, m}]
>From In[34]:= {m, n}

In[35]:= {m, n}
Out[35]= {-5, 25}


(2) The second not so easy part of mysum3 is how the loops are being built
up:

(copied from above)

>            Fold[Function[{i, i0, i1}, 
>                   Unevaluated[For[i = i0, i <= i1, ++i, #1]]] @@ #2 &, 
>             Unevaluated[Unevaluated[s += expr]], 
>             Reverse[{iters}]]

We build up nested For loops as unevaluated code, this is done by the
anonymous function defined, #1 is the inner code to be executed (later) by
the For loop, #2 is the iterator to become the running variable and bounds
of For. The iterators are reversed as to get the last one most deeply
nested. The most inner code (the accumulator, the starting value of #1) is
wrapped into Unevaluated twice, as to (1) prevent evaluation within Fold,
and (2) as argument #1, when applied to the folding function. The
Unevaluated containing the code of the For loop are just eaten up when being
nested (as argument #1 again). What remains is the outermost Unvaluated,
First strips that off (still within Block!) and the loops execute. The
result s of that evaluation is returned. 

--
Hartmut



  • Prev by Date: RE: RE: plot several functions
  • Next by Date: Type 1 Troubles
  • Previous by thread: Re: Setting up dummy variables
  • Next by thread: notebooks and os chrash