# Mapping multiple functions

This question was part of a course on Mathematica written in 1998.

Each of the functions f1, f2, and f3 defined below has a root near x=2. Map an anonymous function involving FindRoot[] onto the list {f1,f2,f3} to find all three roots.

 f1[x_]= 2x-17Cos[x]
f2[x_]= x^2-3Sin[x]
f3[x_]= 2Sin[x]^2-x
Plot[{f1[x],f2[x],f3[x]},{x,0,5}]


Which produced the output:

Out[242]= 2 x - 17 Cos[x]

Out[243]= x^2 - 3 Sin[x]

Out[244]= -x + 2 Sin[x]^2

And then proceeds to draw a nice graph, showing that all of these functions have a root between @1.5 and 1.8. I then individually evaluated the roots (near two) for each function so that I would know if the answers to the "mapped" functions were correct. FindRoot[f1, {2}]

Out[287]= {1.40477}

FindRoot[f2, {2}]


Out[284]= {1.72213}

 FindRoot[f3, {2}]


Out[285]= {1.84908}

Here are some of my attempts to answer the question using Map and FindRoot along with the error messages and output that each produced. (* Note that I attempted about half a dozen other solutions, but did not want to make this post too long*)

 Map[FindRoot, {f1, f2, f3}, {1}]


During evaluation of In[296]:= FindRoot::argmu: FindRoot called with 1 argument; 2 or more arguments are expected. >>

During evaluation of In[296]:= FindRoot::argmu: FindRoot called with 1 argument; 2 or more arguments are expected. >>

During evaluation of In[296]:= FindRoot::argmu: FindRoot called with 1 argument; 2 or more arguments are expected. >>

During evaluation of In[296]:= General::stop: Further output of FindRoot::argmu will be suppressed during this calculation. >>

Out[296]= {FindRoot[f1], FindRoot[f2], FindRoot[f3]}

     Map[FindRoot, {[f1, {2}], [f2, {2}], [f3, {2}]}]


During evaluation of In[303]:= Syntax::sntxf: "{" cannot be followed by "[f1,{2}],[f2,{2}],[f3,{2}]}".

During evaluation of In[303]:= Syntax::tsntxi: "[f1,{2}]" is incomplete; more input is needed.

During evaluation of In[303]:= Syntax::sntxi: Incomplete expression; more input is needed .

     Map[FindRoot, {{f1, {2}}, {f2, {2}}, {f3, {2}}}]


During evaluation of In[303]:= FindRoot::argmu: FindRoot called with 1 argument; 2 or more arguments are expected. >>

During evaluation of In[303]:= FindRoot::argmu: FindRoot called with 1 argument; 2 or more arguments are expected. >>

During evaluation of In[303]:= FindRoot::argmu: FindRoot called with 1 argument; 2 or more arguments are expected. >>

During evaluation of In[303]:= General::stop: Further output of FindRoot::argmu will be suppressed during this calculation. >>

Out[303]= {FindRoot[{f1, {2}}], FindRoot[{f2, {2}}], FindRoot[{f3, {2}}]}

I have read the documentation on Map, FindRoot, Listable, Fold and Function. None of these gave me an idea of how to answer this question. In addition I ran a search of this site(and also looked at each of the threads that were linked when I filled in the subject), the "comp.soft-sys.math.mathematica" site, as well as a general Internet search for "Mapping multiple functions in Mathematica", and didn't find anything that gave me an idea of how to answer the question. I would appreciate someone pointing me in the right direction.

-
"anonymous function" - so, you'll also want to look at the documentation for Slot[] in addition to the one you already read for Function[]. In this case, since FindRoot[] takes two arguments, insert a slot as one of the arguments, and then you can use Function[]. –  Guess who it is. May 23 '13 at 18:44
The title is a bit misleading---here you are mapping a single function onto a list of functions. –  Szabolcs May 23 '13 at 19:15
@Szabolcs, Sorry, I was confused about what I was asking, looking at the answer below I now understand what you are saying. –  Clif May 23 '13 at 19:51

One way to do this:

 Map[FindRoot[#, {2}] &, {f1, f2, f3}]


 {{1.40477}, {1.72213}, {1.84908}}


The point here (as J.M. was suggesting) is that you can use the Slot (the symbol #, which is used to represent arguments or formal parameters in pure functions) to act as a placeholder that will get filled with each of the f1, f2 and f3 in turn. Note that # is always paired with &. You could also use the shortcut (the "infix" form) for Map if you wanted a slicker representation

FindRoot[#, {2}] & /@ {f1, f2, f3}


which returns the same answer. Another way to do this is to use MapThread rather than Map, for instance:

MapThread[FindRoot, {{f1, f2, f3}, {{2}, {2}, {2}}}]


which "threads" the FindRoot function through both arguments and again gives the same result. This has the advantage that you can use different starting values in both arguments (i.e., some of the {2}'s in the original problem could be changed).

-
Thank You. To be sure that I understand about this the [#,{2}] is fulfilling the requirements of FindRoot[italic_function, starting point_italic] while the comma after the & is a requirement of Map[italic_function,expression_italic]. –  Clif May 23 '13 at 20:08
I might say it this way: FindRoot[#, {2}] & is the first argument of Map and {f1, f2, f3} is the second argument of Map. These need to be separated by a comma. –  bill s May 23 '13 at 20:18
code Map[FindRoot[#1, {#2}] &, [{f1, f2, f3}, {2, 0, 2}]] If I could ask an additional question, why won't this work, it would seem that #1 should be pulling from the {f1...}list and #2 should be pulling from the {2,0,2} list. However all that I get is an error message saying that more input is needed. –  Clif May 23 '13 at 20:20
I just added this approach to the answer -- you can do it this way, but it requires MapThread rather than Map. –  bill s May 23 '13 at 20:25
Yes that does work well and that way I can change the "starting from point" values –  Clif May 23 '13 at 20:31

MapThread answer I really like for individual seeds can be specified. A constant alternative to Map is Table where you cycle through a list of functions:

fun = {
2 # - 17 Cos[#] &,
#^2 - 3 Sin[#] &,
2 Sin[#]^2 - # &};

Table[FindRoot[f[x], {x, 2}], {f, fun}]


{{x -> 1.40477}, {x -> 1.72213}, {x -> 1.84908}}

Modifying Table to variable seeds:

With[{s = {1.5, 1.7, 2.}},
Table[FindRoot[fun[[i]][x], {x, s[[i]]}], {i, 3}]]


What about just Thread?

Thread[f[{f1, f2, f2}, {a, b, c}]]


{f[f1, a], f[f2, b], f[f2, c]}

Yet this doesn't work:

Thread[FindRoot[#1[x], {x, #2}] &[fun, {1.5, 1.7, 2.}]]


Because Thread first evaluates its argument (fun[x] gives error). So I try:

Thread[Unevaluated[FindRoot[#1[x], {x, #2}] &[fun, {1.5, 1.7, 2.}]]]


But it still doesn't work. Can somebody enlighten on this, anybody?

-
what helps with Thread is preparing the arguments as Lists of length three (one the first level, i.e. not {x,{1.5,1.7,2.}}, neither {f1,f2,f3}[x] which no longer has Head List). Then Hold on FindRootand it works: Thread[(Hold@FindRoot)[#1, #2] &[ Through[fun[x]], {x, #} & /@ {1.5, 1.7, 2.}]] // ReleaseHold. I hope it is more or less clear what I try to say... –  Pinguin Dirk May 24 '13 at 10:21
@PinguinDirk MapThread! :) –  BoLe May 24 '13 at 10:30
just wanted to force Thread on the problem :) –  Pinguin Dirk May 24 '13 at 10:31