Re: Is it possible to impose a condition on an iterator of
- To: mathgroup at smc.vnet.net
- Subject: [mg101556] Re: [mg101499] Is it possible to impose a condition on an iterator of
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Fri, 10 Jul 2009 06:43:40 -0400 (EDT)
- References: <200907090552.BAA16854@smc.vnet.net>
Hi Mauro, You can use the particular syntax of Sum which allows to supply a list of values to be summed over: In[1] = With[{iterlist = Select[Range[1, 20] , # <= 6 || # >= 12 &]}, Sum[a^2 - 3 a/(4 a^2), {a, iterlist}]] Out[1] = 69209343871/28217280 This is however not very general. What if, for instance, you need to do a multi-dimensional sum and exclude some points according to the test that mixes different coordinates (iteration variables). Here is my attempt to implement a function with such additional functionality but with the standard iterator syntax of Sum: In[2] = ClearAll[conditionalSum]; SetAttributes[conditionalSum, HoldAll]; conditionalSum[expr_, test_, iterators__] := With[{heldVars = Replace[Hold[iterators], {var_, __} :> var, 1]}, Block @@ Append[Replace[heldVars, Hold[vars___] :> Hold[{vars}], {0}], Unevaluated[ With[{itervalues = Flatten[Table[ If[TrueQ[test], List @@ heldVars, Sequence @@ {}], iterators], Length[Hold[iterators]] - 1]}, Total@Map[expr /. Thread[List @@ heldVars -> #] &, itervalues]]]]]; This uses the fact that Table has the same iterator syntax as Sum and can be used to generate expression values and filter out points on which <test> does not give True. It also uses Block to localize iteration variables, so it won't suffer from possible global values set for the iterator variables. So: In[3] = a = 1; conditionalSum[a^2 - 3 a/(4 a^2), a <= 6 || a >= 12, {a, 1, 20}] Out[3] = 69209343871/28217280 (I gave a global value to <a> deliberately). This will sum over 3 coordinates, with all 3 iterators using different iterator sematics: In[4] = conditionalSum[i + j + k, i + j + k < 8, {i, 3}, {j, 1, 4, 1}, {k, {1, 3, 4, 6}}] Out[4] = 116 It can also handle cases when the limits of the "outer" variables depend on inner variables: In[5] = conditionalSum[i + j + k, i + j + k < 8, {i, 3}, {j, 1, i, 1}, {k, {1, 3, 4, 6}}] Out[5] = 68 I did a few more tests indicating that this works correctly, but I don't exclude the possibility of some subtle bugs that I failed to spot. I did not supply type-checks for the input parameters (iterators in particular) and error messages (this can be done easily). Also, I don't know which cool features of the standard Sum I am missing with this approach - perhaps there are lots of symbolic simplifications or built-in rules associated with Sum, also it is certainly faster. But for some simple things conditionalSum may be convenient. Hope this helps. Regards, Leonid On Wed, Jul 8, 2009 at 10:52 PM, Mauro <mauro at nonoyahoo.com> wrote: > I would like to perform a summation of this type, > > Sum[a^2 - 3 a/(4 a^2), {a, 1, 20}] > > excluding however some values of the iteratore, I would for instance > like to exclude the values than to greater of 6 and inferior to 12. Is > it possible? > > Thanks > >
- References:
- Is it possible to impose a condition on an iterator of the summation ?
- From: Mauro <mauro@NONOyahoo.com>
- Is it possible to impose a condition on an iterator of the summation ?