4
$\begingroup$

I have a multivariate polynomial x. I get coefficients of various monomials using CoefficientRules, which returns a list of replacement rules. I now want to apply a function, say ^2 on these coefficients.

My current method is as follows:

c = CoefficientRules[Expand[x]];
Table[{c[[i]][[1]] -> c[[i]][[2]]^2}, {i, 1, Length[c]}]

Is this the conventional way to do it? I find myself using Table all the time for iterating, but is there a better way to do this, say using Thread or Map?

More generally, when is it advisable to use Table? Most of my data is usually an instance of a (multidimensional) List and I find myself constructing iterators over them.

I looked at these questions and suspect that my method is probably not optimal, but I can't say if the other methods are better than Table.

Thanks!

Update:

In[64]:= Mean[First /@ Table[ClearSystemCache[]; 
AbsoluteTiming[Table[c[[i]][[1]] -> c[[i]][[2]]^2, {i,1,Length[c]}];], {692}]]

Out[64]= 0.000386799

In[63]:= Mean[First /@ Table[ClearSystemCache[]; AbsoluteTiming[c /. HoldPattern[a_ -> b_] :> a -> b^2;], {1067}]]

Out[63]= 0.000161383

In[61]:= Mean[First /@ Table[ClearSystemCache[]; AbsoluteTiming[MapAt[#1^2 &, c, {All, 2}];], {1336}]]

Out[61]= 0.000140475

In[58]:= f = # -> #2^2 & @@@ # &;

In[60]:= Mean[First /@ Table[ClearSystemCache[]; AbsoluteTiming[f[c];], {1627}]]

Out[60]= 0.000175706

MapAt seems to have won it. The syntax seems natural enough.

$\endgroup$
3
$\begingroup$

When dealing with a list of rules ({a->b, c->d, ...}) you might also be interested in converting it first into an Association, which allow efficient treatment of its elements and with some more simple syntax.

For example in your case:

taking @March example:

poly = Array[# a[#] x^# &, 5] 
(* x a[1] + 2 x^2 a[2] + 3 x^3 a[3] + 4 x^4 a[4] + 5 x^5 a[5] *)

c = CoefficientRules[Expand[poly], x]
(* {{{1} -> a[1]}, {{2} -> 2 a[2]}, {{3} -> 3 a[3]}, {{4} -> 4 a[4]}, {{5} -> 5 a[5]}} *)

you convert c into an Association with:

ca = Association[c]
<|{1} -> a[1], {2} -> 2 a[2], {3} -> 3 a[3], {4} -> 4 a[4], {5} -> 5 a[5]|>

Now, Map does exactly what you ask for:

Map[f, ca]
<|{1} -> f[a[1]], {2} -> f[2 a[2]], {3} -> f[3 a[3]], {4} -> f[4 a[4]], {5} -> f[5 a[5]]|>

it maps f directly to left hand side of the rule (the value part of this key->value structure). This is exactly what @March's MapAt example does.

But you might be also interested in the KeyMap and KeyValueMap functions.

$\endgroup$
  • $\begingroup$ Wonderful answer! I think I now am more at home with pure functions in Mathematica, and learning Associations now makes me feel immediately at home. I am going to accept this, even though the question was already answered by the others, because 1) It taught me something new, 2) Seems to perform better, and 3) @kglr and @march have loads of reputation anyway. $\endgroup$ – Abhinav Apr 17 '16 at 4:20
  • 1
    $\begingroup$ @Abhinav Thanks ! (The rule for the accept is to choose what answer fits your needs the best, so it's ok here. But maybe next time, you just should wait a little bit more - 24h - before accepting.). Anyway, Association has been introduced not so long time ago, it is very useful and important. However, you should also try to understand the other (traditionnal) approaches which you'll also need soon or late ;) $\endgroup$ – SquareOne Apr 17 '16 at 14:01
7
$\begingroup$

Here are a couple of options. Given:

poly = Array[# a[#] x^# &, 5]
(* x a[1] + 2 x^2 a[2] + 3 x^3 a[3] + 4 x^4 a[4] + 5 x^5 a[5] *)

We can do

c = CoefficientRules[Expand[poly], x]
c /. HoldPattern[a_ -> b_] :> (a -> b^2)
(* {{5} -> 5 a[5], {4} -> 4 a[4], {3} -> 3 a[3], {2} -> 2 a[2], {1} -> a[1]} *)
(* {{5} -> 25 a[5]^2, {4} -> 16 a[4]^2, {3} -> 9 a[3]^2, {2} -> 4 a[2]^2, {1} -> a[1]^2} *)

or

MapAt[#^2 &, c, {All, 2}]
(* {{5} -> 25 a[5]^2, {4} -> 16 a[4]^2, {3} -> 9 a[3]^2, {2} -> 4 a[2]^2, {1} -> a[1]^2} *)
$\endgroup$
  • $\begingroup$ Thanks for the answer! I had tried using Map, but it didn't occur to me to look at MapAt, which extends Map to apply on parts of an expression. I am trying to understand how HoldPattern works. $\endgroup$ – Abhinav Apr 16 '16 at 16:37
4
$\begingroup$
f = # -> #2^2 & @@@ # &;

poly = Plus @@ Array[# a[#] x^# &, 5];
c = CoefficientRules[poly, x]

{{5} -> 5 a[5], {4} -> 4 a[4], {3} -> 3 a[3], {2} -> 2 a[2], {1} -> a[1]}

f@c

{{5} -> 25 a[5]^2, {4} -> 16 a[4]^2, {3} -> 9 a[3]^2, {2} -> 4 a[2]^2, {1} -> a[1]^2}

$\endgroup$
  • $\begingroup$ thanks! This too seems pretty nice! Can you parse the definition of the function f? Are there advantages to defining it as a pure function? $\endgroup$ – Abhinav Apr 16 '16 at 16:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.