Re: Defining two functions at once?
- To: mathgroup at smc.vnet.net
- Subject: [mg70764] Re: [mg70730] Defining two functions at once?
- From: Andrzej Kozlowski <akoz at mimuw.edu.pl>
- Date: Thu, 26 Oct 2006 02:39:21 -0400 (EDT)
- References: <200610250539.BAA28821@smc.vnet.net>
On 25 Oct 2006, at 14:39, AES wrote: > I want to define two functions at once, where both of their values > depend on the same two variables, and both of their values come out > of a > single two-dimensional FindRoot which I'd rather not evaluate twice. > > The following approach seems to work fine for a *single* function > > f[x_, y_] := Module[{}, > myEqns = {f1 - g1 == x1 + 3y1, f1 + g1 == 2x1 - 7y1}; > myValues = {x1 -> x, y1 -> y}; > mySolns = FindRoot[ myEqns /. myValues, {f1, 0} , {g1, 0}]; > f1 /. mySolns] > > But if I try to define two functions at once by replacing the first > and > last lines with > > {f[x_, y_], g[x_,y_]} := Module[{}, > myEqns = {f1 - g1 == x1 + 3y1, f1 + g1 == 2x1 - 7y1}; > myValues = {x1 -> x, y1 -> y}; > mySolns = FindRoot[ myEqns /. myValues, {f1, 0} , {g1, 0}]; > {f1, g1} /. mySolns] > > I get a message about "shapes not being the same". In fact, if I just > make the first and last lines even a single element list, e.g. > > {f[x_, y_]} := Module[{}, > myEqns = {f1 - g1 == x1 + 3y1, f1 + g1 == 2x1 - 7y1}; > myValues = {x1 -> x, y1 -> y}; > mySolns = FindRoot[ myEqns /. myValues, {f1, 0} , {g1, 0}]; > {f1} /. mySolns] > > this doesn't work either. > > If a module supposedly returns the result of its (compound) > expression, > and the final term in that expression is a list, shouldn't the final > example work? More important (to me anyway): Is there a simple way to > define two functions that use a shared FindRoot evaluation in a way > that > (a) evaluates the FindRoot only once, and (b) involves only a single > compound expression of some sort? > I know this is not really relevant here, but I feel I should mention the fact that there is absolutely no point in using Module without any local variables; if you do not need local variables you will do better to enclose the right hand side in parentheses (or use explicit Composition[....,....,...]). Now to answer your question. You can only use lists with SetDelayed with lists if both sides have the head List *before evaluation* and the lists have the same shape. However, before evaluation your right hand side has Head Module, before Evaluation so your approach can't work. This problem would disappear if you used Set (=) instead of SetDelayed but another would take its place: the right hand side would be evaluated immediately, but then FindRoot would produce an error since it would no be able to solve the equations without numerical values for x and y. The simplest way do deal with your problem requires a lot of typing (or at east copying and pasting): {f[x_, y_], g[x_, y_]} := {Module[{myEqns, myValues, mySolns, x1, y1, f1, g1}, myEqns = {f1 - g1 == x1 + 3*y1, f1 + g1 == 2*x1 - 7*y1}; myValues = {x1 -> x, y1 -> y}; mySolns = FindRoot[myEqns /. myValues, {f1,0},{g1,0}];f1 /. mySolns],Module[{myEqns, myValues, mySolns}, myEqns = {f1 - g1 == x1 + 3*y1, f1 + g1 == 2*x1 - 7*y1};myValues = {x1 -> x, y1 -> y};mySolns = FindRoot[myEqns /. myValues, {f1, 0}, {g1, 0}]; g1 /. mySolns]} This long-winded method will indeed define two functions in "one go": In[3]:= Through[{f,g}[1,2]] Out[3]= {-2.5,-9.5} Actually, I can see another way, which uses only one Module, but as I do not think it is any better than the above one, I will only describe it in words and leave implementation to anyone who sees more value in it than I do. Basically the idea is first, to replace SetDelayed by Set, so that the right hand side is evaluated immediately and then to re-write the right hand side so that it will evaluate to a list with two elements. In order to do this you would need to prevent FindRoot and Replace from trying to evaluate prematurely. This could be done, for example, by using a list of two conditional statements of the form {If[Element[Complexes, x|y], FindRoot....., If[Element[Complexes,x|y],FindRoot.....}. In other words the right hand side should immediately evaluate to a list of two conditional expressions, which will return the values of f[x,y] and g[x,y] when x and y are numerical. Andrzej Kozlowski
- References:
- Defining two functions at once?
- From: AES <siegman@stanford.edu>
- Defining two functions at once?