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 ?